5

Consider the following assumptions about C programming (some of which go too far, I confess):

  • Putting any variable definitions in a header file is incorrect, because each translation unit creates its own copy of the data. And if it's extern and used from more than one place, we get UB. The correct usage is to declare variables in header files and define them in the corresponding implementation files.

  • Macros are bad form and can usually be converted to variables or functions.

  • Redeclaration of functions is completely legal.

PROVIDED the above is followed, include guards become unnecessary. There is an exception for inline functions, which have to be defined in the header, but many projects do not use them.

Given all of that, why is the include guard an industry standard? Most IDEs even add them automatically upon file creation.

4
  • 4
    Just a few random guesses: cyclic includes from headers, performance (if a.h includes 5 headers, you don't want a.h to be expanded in full again), and of course the power to not include a header included by one you do want, by just #defineing the guard. Nov 27, 2015 at 7:34
  • 4
    Macro definitions can be repeated. Type definitions can't and are common enough in headers to warrant the systematic use of guards. Cyclic includes seem a bad idea and difficult to make work, if you have one such example which would not be better re-factorized I'm interested in it. Playing tricks by defining the guard in another place than the header seems a recipe for issues later on. Nov 27, 2015 at 7:45
  • Another useful thing is, when you try to cover your code with unit tests and you want to avoid including the world. You just define these guards and then you only provide definitions as required for unit testing.
    – thepacker
    Nov 28, 2015 at 18:59
  • "Most IDEs even add them automatically upon file creation" - this is not quite true. IDEs have templates, and those templates have the include guards. You can normally modify the templates how you like - I normally replace those with #pragma once because that syntax is easier for me to read and is supported by every compiler I've ever used and likely will continue to be supported.
    – Brandin
    Dec 1, 2015 at 10:32

1 Answer 1

12

In many (most?) non-trivial projects, header files contain typedef declarations or struct definitions. Neither of these are allowed to be repeated in a single translation unit (pre-processed source file).

As there are non-repeatable elements that are commonly placed in header files, and those elements also belong in a header file, it has become automatic for C (and C++) programmers to put include guards in their headers.

In C++, it is even more common, as inline functions are used much more and class definitions have the same restriction as struct definitions that they can't be repeated.

5
  • Agreed. It does not help that in C++ it is possible (and sometimes really the only way of getting an outcome) to have code in the header file. This causes a lot of confusion and the C / C++ divide is larger than many think. A mindset flip is needed to swap between C and C++ really effectively Nov 27, 2015 at 7:59
  • It appears I overlooked quite a few things. Btw you could add the cyclic dependency issue, mentioned by AProgrammer.
    – Vorac
    Nov 27, 2015 at 8:02
  • @Vorac: Include guards can break the cycle of a cyclic dependency, but they don't help in the dependency part. Nov 27, 2015 at 9:08
  • We do that with forward declarations, rights?
    – Vorac
    Nov 27, 2015 at 14:13
  • @Vorac: Forward declarations indeed help in breaking dependency cycles, but that is independent of the use of headers. Nov 27, 2015 at 14:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.