Header Guards

This idea of being able to include a file as often as needed does not occur automatically. An example will illustrate the problem.

Two classes and their header files are shown below:

                           #include "A.h"          #include "A.h"
class A                    class B                 #include "B.h"
{                          {
  int x;                      A a;
public:                       int y;               A a;
};                         public:                 B b;
                           };


     A.h                       B.h                      htest.cc
Running g++ htest.cc results in the following error:
In file included from B.h:1,
                 from htest.cc:2:
A.h:2: error: redefinition of `class A'
A.h:2: error: previous definition of `class A'
The class A is being defined twice, once when it is included in htest.cc and once when it is included into B.h which is included in htest.cc.

One way of solving this problem is to remove the line #include "A.h" from htest.cc. But this means that a programmer must be aware of the relationship between A and B. If an instance of A is to be used, A.h should be included. Except when a B instance is used, then A should not be included even though it is used in the source code file. Not fun.

A better way to solve this problem is through the use of header guards. Header guards are little pieces of code that protect the contents of a header file from being included more than once.

Header guards are implemented through the use of preprocessor directives. The C/C++ preprocessor directives all start with the # character. You are already familiar with some ( #include, #define). The preprocessor performs some simple textual replacements on a file before handing it off to the compiler.

Some if the preprocessor directives are conditional. The #ifdef SYMBOL directive is true when SYMBOL has been defined in the code seen so far. If the directive is true, then the statements that come between the #ifdef and an #endif directive later on will be used in the program. If the #ifdef is false, then the statements from that point on will be ignored and not sent to the compiler.

(A quick way to comment out large sections of code is to put a #if 0 at the beginning of the code to be commented and a #endif at the end.)

Another usefule preprocessor directive is #ifndef SYMBOL. This directive is true if the symbol has not been defined. Like other conditional directives, if the condition is true then the statements between the #ifndef and an #endif will be used in the program.

Header guards are implemented by using three preprocessor directives in a header file. Two are placed at the beginning of the file, before any pertinent code. The last is placed at the end of the file. The first header guard line is of the form

#ifndef MY_SYMBOL_H
and is followed immediately by the line
#define MY_SYMBOL_H
The line
#endif /* MY_SYMBOL_H */
is placed at the end of the file.

Important Point
To create header guards place
#ifndef unique_symbol
#define unique_symbol
at the beginning of the header file to be protected and #endif /* unique_symbol*/ at the end of the header file.

The symbol used is not crucial, but it must be unique. It is traditional to use all capital letters for the symbol. Only letters, numbers and the underscore character can be used in the symbols. No other punctuation is allowed. A very common symbol is to use the name of the header file, converting the .h suffix to a _H.

The purpose of this symbol is to serve as a marker. If the symbol is defined then this section of code has been seen before and should not be processed again. If the symbol has not been created, then the code it is associated with has not been seen.

Using the example above, the files become

#ifndef A_H                #ifndef B_H
#define A_H                #define B_H 

                           #include "A.h"          #include "A.h"
class A                    class B                 #include "B.h"
{                          {
  int x;                      A a;
public:                       int y;               A a;
};                         public:                 B b;
                           };

#endif /* A_H */           #endif /* B_H */

     A.h                       B.h                      htest.cc

Some analysis is in order. The first time one of the unique symbols in a header guard is encountered, the #ifndef statement is true. The symbol is not defined. Because of that, all of the code between the #ifndef and #endif is included and sent to the compiler. If the symbol were defined, the code between the directives would be ignored.

After getting past the #ifdef the header guard symbol is immediately defined. (No value is given. It's not needed.) This insures that the first time through the #ifdef will be the only time that the symbol is undefined. The code being protected will only be seen once, no matter how many times the header file is included.

The C style comment after the #endif directive is not mandatory, but it is considered good style.

Kirk L. Duffin 2007-08-27