Thread: Headers are making my head hurt...

  1. #1
    Registered User
    Join Date
    May 2018
    Posts
    11

    Headers are making my head hurt...

    The long version:
    I'm experimenting with an old (8-bit, pre-ANSI) C implementation, and I've run out of memory.

    A solution given in the manual: "don't despair; split the big source file into two or more smaller source files and compile them separately. They will join up again when you link them." Of course, if I compile each piece separately, the compiler complains about "undeclared identifiers" etc.

    Header files seem like a possible solution... but what I've tried doesn't work, and the material I've read seems much more complex than what I'm trying to do.


    TLDR: I want to create header files for a long program which has been split into small units. Existing documentation is confusing.

    I'd really appreciate any guidance in how to fashion a header file for this situation.

    Thanks, Michael

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    Do you have lots of global variables as well as functions?

    It's generally simpler if you restrict the first pass through the code to only move functions that don't depend on global variables.

    Let's say your "large" main.c file consists of two functions.
    Code:
    #include <stdio.h>
    #include <string.h>
    
    void foo ( const char *s ) {
    }
    
    int main ( ) {
        foo("hello");
    }
    In three separate editor windows, open (or create) three files:
    - main.c
    - functions.c
    - functions.h

    Initialise functions.c to look like this
    Code:
    #include <stdio.h>
    #include <string.h>
    #include "functions.h"
    Initialise functions.h to look like this
    Code:
    #ifndef FUNCTIONS_H_INCLUDED
    #define FUNCTIONS_H_INCLUDED
    
    // Prototypes go here
    
    #endif
    After the system includes in main.c, add the line
    Code:
    #include "functions.h"
    One by one, you then do the following things.
    1. Cut the code for the 'foo' function from main.c
    2. Paste the code for the 'foo' function to the end of functions.c
    3. Declare a prototype for the 'foo' function in functions.h

    So like this.
    Main.c
    Code:
    #include <stdio.h>
    #include <string.h>
    #include "functions.h"
    
    // foo cut from here
    
    int main ( ) {
        foo("hello");
    }
    Functions.c
    Code:
    #include <stdio.h>
    #include <string.h>
    #include "functions.h"
    
    // foo pasted here
    
    void foo ( const char *s ) {
    }
    Functions.h
    Code:
    #ifndef FUNCTIONS_H_INCLUDED
    #define FUNCTIONS_H_INCLUDED
    
    // Prototypes go here
    void foo ( const char *s );
    
    #endif
    After each move of a function, compile everything to make sure it still works.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    May 2018
    Posts
    11
    Thank you for your reply. Ok I've read through your answer several times, and looked at some other tutorials. I tried again, and either I'm still doing it wrong or the compiler isn't very good...

    I'm testing with two files:
    INIT.C has lots of global variables, and one function called wipe() which clears the screen.
    INTRO.C uses some of the global variables, as well as the wipe() function.

    Here's what I did:


    INIT.C

    Code:
    #include <stdio.h>
    #include <string.h>
    
    #define true 1
    #define false 0
    
    int lots      =1;
    int of        =2;
    int variables =3;
    
    wipe() { code };
    INIT.H

    Code:
    #ifndef INIT_H_INCLUDED
    #define INIT_H_INCLUDED
    
    #define true 1
    #define false 0
    
    extern int lots, of, variables;
    
    wipe();
    
    #endif
    INTRO.C
    Code:
    #include <stdio.h>
    #include <string.h>
    #include "INTRO.H"
    
    main()
    {
    foo() { code with variables };
    wipe();
    }
    INIT.C compiles fine, but INTRO.C goes all the way to the end and freezes. I realize this could be a bug in the compiler, but am I doing anything wrong in the examples above?
    Last edited by gmontag451; 12-04-2022 at 03:52 PM.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    You show a file called INIT.H, but you include a file called "INTRO.H"

    INIT.C should include INIT.H
    This keeps the prototype/definition of wipe() in sync, and you don't have to keep redefining true and false.

    Copy/pasting your actual console/terminal log of the compilation would be useful.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    May 2018
    Posts
    11
    Sorry that was a typo, I should have chosen different names for my example! INTRO.C does indeed say #include "INIT.H"

    I wish there was a terminal log/error message to copy and paste... It's an old Commodore 64 implementation, and at best I'm lucky to get "syntax error" or "illegal assignment", at worst it just freezes up like it's doing now.

    I think I need to download a version of C for Windows and get it working first, before trying to figure out what's going on with the Commodore version. Thanks for your suggestions, I'll come back and update when I've played with it in Windows!

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    Yeah, old 1980's 8-bit micro C implementations were a challenge for sure.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User
    Join Date
    May 2018
    Posts
    11
    I think I figured it out. I got everything working in a browser compiler (OnlineDGB) and copied the working headers over to the Commodore for partial success.

    I haven't figured out when to use "extern". In OnlineDGB and on the Comodore 128 the program works fine with or without extern. But without extern, the Commodore 64 throws a lot of errors--and with extern it still runs out of memory! Oh well, it was worth a try. (There are always other solutions like cross-compilers for Windows)

    Thanks for your help, it really helped me to get a grasp on headers.

  8. #8
    Registered User rstanley's Avatar
    Join Date
    Jun 2014
    Location
    New York, NY
    Posts
    1,111
    Quote Originally Posted by gmontag451 View Post
    I think I figured it out. I got everything working in a browser compiler (OnlineDGB) and copied the working headers over to the Commodore for partial success.

    I haven't figured out when to use "extern". In OnlineDGB and on the Comodore 128 the program works fine with or without extern. But without extern, the Commodore 64 throws a lot of errors--and with extern it still runs out of memory! Oh well, it was worth a try. (There are always other solutions like cross-compilers for Windows)

    Thanks for your help, it really helped me to get a grasp on headers.
    All functions are by default, "extern", unless declared/defined as static. At least in a Standards Compliant compiler. Not a error to define them as extern, but not needed.

    I would guess that any compilers for Commodore 64 or 128 are not Standards Compliant.

    I would strongly urge you to abandon both Commodore "computers", and move to Windows, using Cygwin, or MinGW-64, or even better, Linux.

  9. #9
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    Or use the CC65 cross-compiler.

  10. #10
    Registered User rstanley's Avatar
    Join Date
    Jun 2014
    Location
    New York, NY
    Posts
    1,111
    Quote Originally Posted by christop View Post
    Or use the CC65 cross-compiler.
    Not recommended!

    From the CC65 website:
    "Please note that the compiler does not support the C99 standard and never will. c99 mode is actually c89 mode with a few selected C99 extensions."

    Time to move up to Gcc or Clang on Windows or Linux.

  11. #11
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    Quote Originally Posted by rstanley View Post
    Not recommended!

    From the CC65 website:
    "Please note that the compiler does not support the C99 standard and never will. c99 mode is actually c89 mode with a few selected C99 extensions."

    Time to move up to Gcc or Clang on Windows or Linux.
    I agree that for general programming, GCC or Clang on a modern computer is preferred, but for those wanting to develop for the old personal computers like the Commodore, CC65 is one of the best C compilers available. Surely it can't be worse than the native compiler that OP is currently using?

  12. #12
    Registered User
    Join Date
    May 2018
    Posts
    11
    Quote Originally Posted by rstanley View Post
    I would guess that any compilers for Commodore 64 or 128 are not Standards Compliant.
    Due to age and memory constraints, they most certainly are not.

    Quote Originally Posted by rstanley View Post
    I would strongly urge you to abandon both Commodore "computers", and move to Windows, using Cygwin, or MinGW-64, or even better, Linux.
    Thanks, I'll look into Cygwin an Clang. I'm not an experienced programmer, but I'm familiar with MinGW and Gcc, in both Windows and Linux.
    The point of this project was to get a specific program working on the C64, which is the computer (no quotes needed! ) which I grew up with.

    Quote Originally Posted by christop View Post
    Or use the CC65 cross-compiler.
    I think you're right, I've used CC65, and cross-compiling is probably the better/only solution, even if it's not as fun!

  13. #13
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    Quote Originally Posted by gmontag451 View Post
    I think you're right, I've used CC65, and cross-compiling is probably the better/only solution, even if it's not as fun!
    I'm just curious, but which C64 C compiler are you using? The only one I've heard of is Super-C. I've never played with it myself, but I can see how it would be fun to get a program working with it (it would have lots of nostalgia value since I also grew up with the C64 and used mine quite a bit until about 10 years ago).

  14. #14
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    I just added cc65 to development MINGW-packages-dev/mingw-w64-cc65 at master * msys2/MINGW-packages-dev * GitHub git repo.

    In case, you are using MSys2.

    Edit: I have not really used cc65; I am trying to port some m6502 open source projects to the m6809 CPU used by the Radio Shack Color Computer.
    Step 1. Is porting the m6502 projects to MSys2.

    Tim S.
    Last edited by stahta01; 12-09-2022 at 03:07 PM.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  15. #15
    Registered User
    Join Date
    May 2018
    Posts
    11
    Quote Originally Posted by christop View Post
    I'm just curious, but which C64 C compiler are you using? The only one I've heard of is Super-C. I've never played with it myself, but I can see how it would be fun to get a program working with it (it would have lots of nostalgia value since I also grew up with the C64 and used mine quite a bit until about 10 years ago).
    I'm using the same software I originally learned C on; Better Working Power C (which was originally called C Power). Power C has a really nice interface and workflow but there are some frustrating bugs, the documentation is wanting, and there are baffling inconsistencies between the C128 and C64 version. I've never used any other on the 64, but there's really no excuse not to and I'll probably try out Super-C over Christmas break.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 09-28-2012, 10:22 PM
  2. Bolean Operators hurt my head. (Trouble understanding) :(
    By Funcoot in forum C++ Programming
    Replies: 3
    Last Post: 01-20-2008, 07:42 PM
  3. making GUIs with windows headers in C
    By xixpsychoxix in forum C Programming
    Replies: 2
    Last Post: 03-05-2006, 11:47 AM
  4. Making headers...
    By twomers in forum C Programming
    Replies: 1
    Last Post: 01-03-2006, 08:10 AM
  5. ouch thats gotta hurt
    By Thantos in forum A Brief History of Cprogramming.com
    Replies: 13
    Last Post: 08-22-2004, 09:48 AM

Tags for this Thread