Protecting headers from double inclusion¶
For every variable and function in your C program, there is exactly one
definition. If you try to supply two definitions of the same thing, you
will get an error from the linker, ld, when you try to make
your program. Declarations that are not definitions, on the other hand,
can typically be repeated, and it is good style to keep things divided
so that only declarations are in your headers (the .h
files).
Nonetheless, some kinds of declarations cannot be repeated (notably, structures), so in general it would be a problem to include the same header twice. Obviously, nobody is going to just include the same header twice in a row.
#include "myheader.h"
#include "myheader.h"
However, headers often need to include each other—one header might create some type, and then another header might declare a function that returns a value of that type. So, if your code includes both headers, you have now included a header twice—once on purpose, and once implicitly by including another header. It would certainly be possible to solve this sort of problem by carefully documenting what other headers are included in every other header and making sure to include everything you need once and only once, but that would be as annoying as it sounds. Instead, programmers simply add some boilerplate code to their headers so that they are safely skipped if included a second time. (In programming terminology, including headers should be ‘idempotent’, i.e. doing it twice is harmlessly the same as doing it just once.)
We use preprocessor directives for that. Essentially, a ‘header guard’ such as this is an if statement, along the lines of ‘if this header has never been included before, go ahead and provide this code and mark that it has been included, but otherwise, just skip it’.
#ifndef WHATEVER_H
#define WHATEVER_H
/* Put all your declarations here. */
#endif
Typically, the #ifndef
and #endif
lines that delimit
this conditional are the first and last lines of the file. It is safe
to put whitespace and comments outside the conditional, but make sure
all of your C code is inside it.
The WHATEVER_H
symbol in the example is a unique identifier used
to keep track of whether this particular header has been included before
(if it hasn’t been defined, define it, etc.). You can choose whatever
symbol you want, but every header needs its own unique one, so typically
people choose something based on the file name itself. I encourage you
to make all letters from the filename uppercase and delete all nonletter
characters or replace them with underscores, so my-header.h
would have a guard symbol like MY_HEADER_H
.