Include header file in C curiosity

I have the following curiosity regarding include files and their management (with GCC


Let's say I have one source file foo.c and three headers foo.h , foo_cfg.h, and foo_int. h .

In foo.c :

#include "foo.h"  
#include "foo_int.h" 


In foo.h :

#include "foo_cfg.h" 


In foo_cfg.h :

/* no inclusions */   
#define FOO BAR


In foo_int.h :

/* no inclusions */ 
#define BAR 0U


I am wondering why the compilation was successful. Should the foo_cfg.h file complain about not knowing about the BAR character?

Also, I have another original bar.c file that only contains the foo.h file and still works.

Note: This is from a project I'm working on with a complex build environment that I don't need to go into detail about. Maybe the build environment affects this differently than specifying the location for header files


Perhaps the question is really stupid or I missed something and I apologize.


source to share

2 answers

No it's okay.

You see, the preprocessor doesn't care if BAR is defined or not. It just replaces the line FOO to BAR in the following source code, not caring if it is defined at that point or not.

Further, in the actual file .c

(which is where compilation starts) both headers are included, so the compiler sees both the substitutions: FOO


and BAR


. Therefore, he successfully applies both of them.

Headers are never compiled alone, they are always compiled as part of the file .c

that #include

this header is. (The preprocessor just pretends that the content of the header is inserted where it is #include

.) So, for the preprocessor, your file foo.c

looks like this:

/* no inclusions */
#define FOO BAR
/* no inclusions */
#define BAR 0U
/* the rest of the file... */
/* for example: */
unsigned int i = FOO;


And the compiler, after preprocessing, sees exactly this:

/* no inclusions */
/* no inclusions */
/* the rest of the file... */
/* for example: */
unsigned int i = 0U;


(not really sure, maybe the preprocessor removes comments as well.)

Indeed, as @pmg mentions, the preprocessor replaces comments with a space, so the real preprocessed text that is fed to the compiler is just

unsigned int i = 0U;


( _

denotes a space here )



To add Vlad a little:

Preprocessor macros are expanded when used, not when defined.
So when you write #define FOO BAR

, all it does is remember that FOO = BAR.
When you write #define BAR 0U

, he remembers that BAR = 0U.

Now when FOO

displayed in code, it is replaced with BAR

, which is immediately replaced with 0U

The order in which #define FOO

it #define BAR

appears in the source is unimportant. The important thing is that when FOO

seen for the first time, both definitions have already been met.



All Articles