Ifndef?

The One-Definition Rule: Introducing and explaining include guards.

Henri Woodcock
3 min readApr 28, 2021
Photo by Bruce Warrington on Unsplash

You’ll find macros #ifndef and #define at the top of pretty much every C/C++ header file. However, I could not find any information about this formatting in any books or tutorials I learned from, and if they were, there was no explanation! So what are they?

For a while, I just accepted this was part of coding standards for formatting or readability and just used it myself. It was only when I took an interest in understanding compilers that I realised the purpose and importance of header guards.

Include guards are a construct used at the top of header files to stop some code from being included twice. For example, for a header file header.h the contents of this file may look similar to the following:

#ifndef header_h_
#define header_h_
// code / contents of the file
#endif

Understanding why this is required becomes intuitive when you learn how a C/C++ compiler works. When a program is compiled into an executable the compiler will go through all the source files and convert them into one program. It does this by performing an interim step of converting the source code into one long text file ready to convert to assembly. When a source file has an #include “header.h” the header file is opened and appended into this long text file. Once this is complete the compiler will check the files. For small projects, this does not pose any issues. However, for larger projects, certain header files may be reused multiple times. This would mean these header files are appended to the long text file multiple times and finally, this would lead to a compiler error warning that you have redefined some variables.

This is where include guards come in, the compiler will only include the header file if and if only it has not already been defined. For example, the first time a header is included the compiler will check if header_h has been defined, if not it will define header_h and this code between #define and #endif. The second time this header file is now included the compiler will check if header_h has been defined and because it has it will skip the definition.

This is part of the One Definition Rule, which states that:

“A given class, enumeration, and template, etc., must be defined exactly once in a program.” – The C++ Programming Language, Bjarne Stroustrup.

Example

To see this in action, I have created a two simple examples for comparison. One without header guards and one with.

Without header guards

variables.hint x = 10;
int y = 20;
int x_plus_y = x + y;
use_variables.h#include variables.hmain.cc#include "variables.h"
#include "use_variables.h"
// main now includes 2 copies of x and y from use_variables and variables
#include <iostream>
int main() {
std::cout << x_plus_y << std::endl;
return 0;
}

Running this code results in:

./variables.h:1:5: error: redefinition of 'x'
...
./variables.h:2:5: error: redefinition of 'y'
...
./variables.h:3:5: error: redefinition of 'x_plus_y'

With header guards

variables.h#ifndef variables_h_
#define variables_h_
int x = 10;
int y = 20;
int x_plus_y = x + y;
#endifuse_variables.h#include variables.hmain.cc#include "variables.h"
#include "use_variables.h"
// main now does not redefine x, y and x_plus_y when including
// use_variables.h
#include <iostream>
int main() {
std::cout << x_plus_y << std::endl;
return 0;
}

Compiling this code results in no errors, and running the executable we get 30, as expected.

Summary

To put into one sentence. Header guards are used to stop the compiler including the same code multiple times; this stops any variables, functions, classes etc being defined more than once.

It’s good to get into the habit of starting your header files with these header guards.

--

--

Henri Woodcock

UK Based SWE \\ trckrspace.com \\ The opinions expressed are my own views and not my employer. \\ @henriwoodcock