Why Include Guards

Why include guards?

Simply because you might have wanted the compiler to load that file twice.

Remember, that #include simply loads a file and puts its contents in the place of the directive. This file might be a header file, but may be useful and frequently used piece of source code as well.

Most modern compilers react to #pragma once doing exactly what you want them to. Remember though, that this is a compiler extension not included in the language specification and it is generally a good idea to stick to include guards - you'll be certain, that it works on every compiler and in any circumstances.

C++ #include guards

The preprocessor is a program that takes your program, makes some changes (for example include files (#include), macro expansion (#define), and basically everything that starts with #) and gives the "clean" result to the compiler.

The preprocessor works like this when it sees #include:

When you write:

#include "some_file"

The contents of some_file almost literally get copy pasted into the file including it. Now if you have:

a.h:
class A { int a; };

And:

b.h:
#include "a.h"
class B { int b; };

And:

main.cpp:
#include "a.h"
#include "b.h"

You get:

main.cpp:
class A { int a; }; // From #include "a.h"
class A { int a; }; // From #include "b.h"
class B { int b; }; // From #include "b.h"

Now you can see how A is redefined.

When you write guards, they become like this:

a.h:
#ifndef A_H
#define A_H
class A { int a; };
#endif

b.h:
#ifndef B_H
#define B_H
#include "a.h"
class B { int b; };
#endif

So now let's look at how #includes in main would be expanded (this is exactly, like the previous case: copy-paste)

main.cpp:
// From #include "a.h"
#ifndef A_H
#define A_H
class A { int a; };
#endif
// From #include "b.h"
#ifndef B_H
#define B_H
#ifndef A_H // From
#define A_H // #include "a.h"
class A { int a; }; // inside
#endif // "b.h"
class B { int b; };
#endif

Now let's follow the preprocessor and see what "real" code comes out of this. I will go line by line:

// From #include "a.h"

Comment. Ignore! Continue:

#ifndef A_H

Is A_H defined? No! Then continue:

#define A_H

Ok now A_H is defined. Continue:

class A { int a; };

This is not something for preprocessor, so just leave it be. Continue:

#endif

The previous if finished here. Continue:

// From #include "b.h"

Comment. Ignore! Continue:

#ifndef B_H

Is B_H defined? No! Then continue:

#define B_H

Ok now B_H is defined. Continue:

#ifndef A_H          // From

Is A_H defined? YES! Then ignore until corresponding #endif:

#define A_H          // #include "a.h"

Ignore

class A { int a; };  // inside

Ignore

#endif               // "b.h"

The previous if finished here. Continue:

class B { int b; };

This is not something for preprocessor, so just leave it be. Continue:

#endif

The previous if finished here.

That is, after the preprocessor is done with the file, this is what the compiler sees:

main.cpp
class A { int a; };
class B { int b; };

So as you can see, anything that can get #included in the same file twice, whether directly or indirectly needs to be guarded. Since .h files are always very likely to be included twice, it is good if you guard ALL your .h files.

P.S. Note that you also have circular #includes. Imagine the preprocessor copy-pasting the code of Physics.h into GameObject.h which sees there is an #include "GameObject.h" which means copy GameObject.h into itself. When you copy, you again get #include "Pysics.h" and you are stuck in a loop forever. Compilers prevent that, but that means your #includes are half-done.

Before saying how to fix this, you should know another thing.

If you have:

#include "b.h"

class A
{
B b;
};

Then the compiler needs to know everything about b, most importantly, what variables it has etc so that it would know how many bytes it should put in place of b in A.

However, if you have:

class A
{
B *b;
};

Then the compiler doesn't really need to know anything about B (since pointers, regardless of the type have the same size). The only thing it needs to know about B is that it exists!

So you do something called "forward declaration":

class B;  // This line just says B exists

class A
{
B *b;
};

This is very similar to many other things you do in header files such as:

int function(int x);  // This is forward declaration

class A
{
public:
void do_something(); // This is forward declaration
}

Why aren't include guards in c++ the default?

The behavior of a C++ compiler is specified in terms of how it handles each translation unit. A translation unit is a single file after the preprocessor runs over it. The fact that we have a convention of collecting declarations in certain files and calling them "header" files means nothing to a compiler or the C++ standard.

Simply put, the standard doesn't provide for "header files" so it can't provide for automatically include guarding header files. The standard only provides for the preprocessor directive #include and the rest is merely convention. Nothing stops you from forward declaring everything and not using header files (except pity for whomever should have to maintain that code...).

So header files aren't special and there's no way to say "that's a header file, guard it", but why can't we guard everything that gets #include'd? Because #include is both more and less powerful than a module system like other languages have. #include causes the preprocessor to paste in other files, not necessarily header files. Sometimes this can be handy if you have the same using and typedef declarations in a bunch of different namespaces in different files. You could collect them in a file and #include them in a few places. You wouldn't want automatic include guards preventing you from doing that.

Using #ifndef and #define to conditionally include headers is also merely convention. The standard has no concept of "include guard". (Modern compilers however actually are aware of include guards. Recognizing include guards can allow faster compilation but it has nothing to do with correctly implementing the standard.)

Getting pedantic

The standard does liberally use the word "header", especially in reference to the C and C++ standard libraries. However, the behavior of #include is defined under § 16.2 *Source file* inclusion (emph. mine) and it does not grant any special powers to header files.

There are efforts to get a proper module system into the C++ standard.

Why include guards do not prevent multiple function definitions?

"1) Why do the include guards not prevent multiple definitions of this function like they do for other header items"

Because each translation unit (i.e. .cpp file) is processed separately and goes through the same conditional. Translation units won't share the preprocessor definitions encountered by other translation units. This means that all the translation units that will process that header will include a definition for that function. Of course, the linker will then complain that the same function has multiple definitions.

"2) Why does the static word resolve this when static is supposed to prevent names from visibility in other translation units?"

Because the static keyword makes a private copy of that function for each translation unit.

If you want that function to be defined in a shared header, however, you should rather mark it as inline, which will solve your problem and will make the preprocessor guards unnecessary.

What exactly do C include guards do?

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.

#pragma once vs include guards?

I don't think it will make a significant difference in compile time but #pragma once is very well supported across compilers but not actually part of the standard. The preprocessor may be a little faster with it as it is more simple to understand your exact intent.

#pragma once is less prone to making mistakes and it is less code to type.

To speed up compile time more just forward declare instead of including in .h files when you can.

I prefer to use #pragma once.

See this wikipedia article about the possibility of using both.

C: Extern variable declaration and include guards

Include guards are useful for preventing multiple delcarations or type definitions in a single translation unit, i.e. a .c file that is compiled by itself along with all of the headers it includes.

Suppose you have the following headers without include guards:

a.h:

struct test {
int i;
};

struct test t1;

b.h:

#include "a.h"

struct test *get_struct(void);

And the following main file:

main.c:

#include <stdio.h>
#include "a.h"
#include "b.h"

int main()
{
struct test *t = get_struct();
printf("t->i=%d\n", t->i);
return 0;
}

When the preprocessor runs on the, the resulting file will look something like this (neglecting the contents of stdio.h):

struct test {
int i;
};

struct test t1;

struct test {
int i;
};

struct test t1;

struct test *get_struct(void);

int main()
{
struct test *t = get_struct();
printf("t->i=%d\n", t->i);
return 0;
}

Because main.c includes a.h and b.h, and because b.h also includes a.h, the contents of a.h appear twice. This causes struct test to be defined twice which is an error. There is no problem however with the variable t1 because each constitutes a tentative definition, and multiple tentative definitions in a translation unit are combined to refer to a single object defined in the resulting main.o.

By adding include guards to a.h:

#ifndef A_H
#define A_H

struct test {
int i;
};

struct test t1;

#endif

The resulting preprocessor output would be:

struct test {
int i;
};

struct test *get_struct(void);

int main()
{
struct test *t = get_struct();
printf("t->i=%d\n", t->i);
return 0;
}

Preventing the duplicate struct definition.

But now let's look at b.c which constitutes a separate translation unit:

b.c:

#include "b.h"

struct test *get_struct(void)
{
return &t1;
}

After the preprocessor runs we have:

struct test {
int i;
};

struct test t1;

struct test *get_struct(void);

struct test *get_struct(void)
{
return &t1;
}

This file will compile fine since there is one definition of struct test and a tentative definition of t1 gives us an object defined in b.o.

Now we link a.o and b.o. The linker sees that both a.o and b.o contain an object called t1, so the linking fails because it was defined multiple times.

Note here that while the include guards prevent a definition from appearing more than once in a single translation unit, it doesn't prevent it from happening across multiple translation units.

This is why t1 should have an external declaration in a.h:

extern struct test t1;

And a non-extern declaration in one .c file.

c++ include guards don't work, error

Include guards guard from a header file being included twice in a single file but here you have two different files. My advice is not to define any variables in header files. Instead declare them as extern and define them in a separate cpp file where you include you header file. This way you will have only one definition but you will have them declared where you use them.



Related Topics



Leave a reply



Submit