The following C code demonstrates a real problem that can arise if #include guards are missing:
File "grandparent.h"
struct foo ;
File "parent.h"
include "grandparent.h"
File "child.c"
include "grandparent.h"
include "parent.h"
Result
struct foo ; struct foo ; Here, the file "child.c" has indirectly included two copies of the text in the header file "grandparent.h". This causes a compilation error, since the structure type foo will thus be defined twice. In C++, this would be called a violation of the one definition rule.
Use of #include guards
Example
In this section, the same code is used with the addition of #include guards. The C preprocessor preprocesses the header files, including and further preprocessing them recursively. This will result in a correct source file, as we will see.
File "grandparent.h"
ifndef GRANDPARENT_H
define GRANDPARENT_H
struct foo ;
endif /* GRANDPARENT_H */
File "parent.h"
include "grandparent.h"
File "child.c"
include "grandparent.h"
include "parent.h"
Result
struct foo ; Here, the first inclusion of "grandparent.h" has the macro GRANDPARENT_H defined. When "child.c" includes "grandparent.h" at the second time, as the #ifndef test returns false, the preprocessor skips down to the #endif, thus avoiding the second definition of struct foo. The program compiles correctly.
Discussion
Different naming conventions for the guard macro may be used by different programmers. Other common forms of the above example include GRANDPARENT_INCLUDED, CREATORSNAME_YYYYMMDD_HHMMSS, and names generated from a UUID. Of course, it is important to avoid duplicating the same include-guard macro name in different header files, as including the 1st will prevent the 2nd from being included, leading to the loss of any declarations, inline definitions, or other #includes in the 2nd header.
Difficulties
In order for #include guards to work properly, each guard must test and conditionally set a different preprocessor macro. Therefore, a project using #include guards must work out a coherent naming scheme for its include guards, and make sure its scheme doesn't conflict with that of any third-party headers it uses, or with the names of any globally visible macros. For this reason, most C and C++ implementations provide a non-standard #pragma once directive. This directive, inserted at the top of a header file, will ensure that the file is included only once. The Objective-C language introduced an #import directive, which works exactly like #include, except that it includes each file only once, thus obviating the need for #include guards.