What exactly do C include guards do?
You prevent the file from being included more than once, here
#ifndef HEADER_FILE
you test if HEADER_FILE
is NOT defined, in case that's true then
#define HEADER_FILE
would define it, now if you include the file in another file, the first time it will define HEADER_FILE
, while the second time, it will be already defined and hence the content of the file is not included again, since the #ifndef HEADER_FILE
will be false.
Remember that these are evaluated by the preprocessor before actual compilation is done, so they are evaluated at compile time.
It's a preprocessor macro.
All of it is preprocessor syntax, that basically says, if this macro has not already been defined, define it and include all code between the #ifndef
and #endif
What it accomplishes is preventing the inclusion of file more than once, which can lead to problems in your code.
Your question:
And why is it okay to forget the include guard in which case we can also forgot adding #define HEADER_FILE?
It's OK to forget it because it's still legal C code without it. The preprocessor processes your file before it's compiled and includes the specified code in your final program if there's no logic specifying why it shouldn't. It's simply a common practice, but it's not required.
A simple example might help illustrate how this works:
Your header file, header_file.h
we'll say, contains this:
#ifndef HEADER_FILE
#define HEADER_FILE
int two(void){
return 2;
}
#endif
In another file (foo.c
), you might have:
#include "header_file.h"
void foo() {
int value = two();
printf("foo value=%d\n", value);
}
What this will translate to once it's "preprocessed" and ready for compilation is this:
int two(void){
return 2;
}
void foo() {
int value = two();
printf("foo value=%d\n", value);
}
All the include guard is accomplishing here is determining whether or not the header contents between the #ifndef ...
and #endif
should be pasted in place of the original #include
.
However, since that function is not declared extern
or static
, and is actually implemented in a header file, you'd have a problem if you tried to use it in another source file, since the function definition would not be included.