Search code examples
cheader-filescode-organization

Where should you put "typedef enum"s in your source?


I'm working on a larger project than I'm used to, and I'm doing my best to keep my code properly structured. I am programming a microcontroller and have some global variables, which as per some advice I read on here are all defined in a "global_variables.h" file which is included anywhere that the global variables are used.

I also put the typedef for the global variables into the "global_variables.h" file.

The problem I am running across is that the file1.c in which I use the global variable has a function1(new_type_t variable) which accepts the new typedef as a parameter. The problem with this is that I have the function1 prototype defined in the header (file1.h), but since the #include "global_variables.h" is located in file1.c, the function prototype in file1.h does not see the typedef.

I feel like this is a common occurrence, but Googling didn't seem to provide too much help. Should I make a separate "global_variables.h" and "global_variables_types.h" and include the .h file in the headers of my other files and the .c in the sources?


Solution

  • I don't think that having a header file global_variables.h is sensible.

    If your project is a small single-person project (e.g. less than 50KLOC = 50 thousand lines of source code), and you don't intend to make a reusable library, having one single header file for all the project is probably sensible. That header file would declare the global variables, and before them the relevant types. You'll also declare all your functions, and at last define all your inlined functions. You could consider having the inlined functions in a separate header file (including from your main header).

    If you intend to make reusable code, make separate headers for separate subsystems of your project. But I don't feel the need to have a header for just all the global variables.

    Most importantly, keep your set of global variables minimal. You should be able to count global variables with the fingers of a single hand. If you need more than 4 or 5 global variables, consider packing related global variables in a global struct. For instance, if the screen size is in global data, don't declare int screen_width, screen_height; but rather

     struct {
        int width;
        int height;
     } screen;
    

    Of course, the true thing depends upon the project, and perhaps upon the build chain. Some proprietary compilers don't really optimize, and might produce bad code if using global structures. If you use a recent GCC (as a cross compiler, preferably on Linux), you don't have that issue, since GCC optimize well. Always enable all warnings on your compiler (e.g. build with gcc -Wall -g -O2)

    A good advice would be to study the source code of some existing free software similar to yours.