cheaderfile-organization

Organization of C files


I'm used to doing all my coding in one C file. However, I'm working on a project large enough that it becomes impractical to do so. I've been #including them together but I've run into cases where I'm #including some files multiple times, etc. I've heard of .h files, but I'm not sure what their function is (or why having 2 files is better than 1).

What strategies should I use for organizing my code? Is it possible to separate "public" functions from "private" ones for a particular file?

This question precipitated my inquiry. The tea.h file makes no reference to the tea.c file. Does the compiler "know" that every .h file has a corresponding .c file?


Solution

  • You should regard .h files as interface files of your .c file. Every .c file represents a module with a certain amount of functionality. If functions in a .c file are used by other modules (i.e. other .c files) put the function prototype in the .h interface file. By including the interface file in your original modules .c file and every other .c file you need the function in, you make this function available to other modules.

    If you only need a function in a certain .c file (not in any other module), declare its scope static. This means it can only be called from within the c file it is defined in.

    Same goes for variables that are used across multiple modules. They should go in the header file and there they have to marked with the keyword 'extern'. Note: For functions the keyword 'extern' is optional. Functions are always considered 'extern'.

    The inclusion guards in header files help to not include the same header file multiple times.

    For example:

    Module1.c:

        #include "Module1.h"
    
        static void MyLocalFunction(void);
        static unsigned int MyLocalVariable;    
        unsigned int MyExternVariable;
    
        void MyExternFunction(void)
        {
            MyLocalVariable = 1u;       
    
            /* Do something */
    
            MyLocalFunction();
        }
    
        static void MyLocalFunction(void)
        {
          /* Do something */
    
          MyExternVariable = 2u;
        }
    

    Module1.h:

        #ifndef __MODULE1.H
        #define __MODULE1.H
    
        extern unsigned int MyExternVariable;
    
        void MyExternFunction(void);      
    
        #endif
    

    Module2.c

        #include "Module.1.h"
    
        static void MyLocalFunction(void);
    
        static void MyLocalFunction(void)
        {
          MyExternVariable = 1u;
          MyExternFunction();
        }