Header file included only once in entire program?

17,679

Solution 1

This is the process:

source           header   source header header
   \           /        \   |      /   /
    \         /          \  |     /   /
  PREPROCESSOR            PREPROCESSOR
       |                      |
       V                      V
 preprocessed code      preprocessed code
       |                      |
    COMPILER               COMPILER
       |                      |
       V                      V
  object code              object code
             \            /
              \          /
               \        /
                 LINKER
                   | 
                   V
               executable

Preprocessing

#include is for this first step. It instructs the preprocessor to processes the specified file, and insert the result into the output.

If A includes B and C, and B includes C, the preprocessor's output for A will include the processed text of C twice.

This is a problem, since it will result in duplicate declarations. A remedy is to use preprocessor variables track whether the source code has been included (aka header guards).

#ifndef EXAMPLE_H
#define EXAMPLE_H

// header contents

#endif

The first time, EXAMPLE_H is undefined, and the preprocessor will evaluate the contents within the ifndef/endif block. The second time, it will skip that block. So the processed output changes, and the definitions are included only once.

This is so common that there is a non-standard directive implemented by some compilers that is shorter and does not require choosing a unique preprocessor variable:

#pragma once

// header contents

You can figure out how portable you want your C/C++ code, and which header guard to use.

Headers guards will ensure the contents of each header file are present at most once in the preprocessed code for a translation unit.

Compiling

The compiler generates machine code from your preprocessed C/C++.

Generally, the header files only include declarations, not the actual definitions (aka implementations). The compiler includes a symbol table for anything that is currently missing an definition.

Linking

The linker combines the object files. It matches up the definitions (aka implementations) with the references to the symbol table.

It may be that two object files provide the definition, and the linker will take one. This happens if you've put executable code in your headers. This generally does not happen in C, but it happens very frequently in C++, because of templates.

The header "code", whether declarations or definitions, is included multiple times across all object files but the linker merges all of that together, so that it is only present once in the executable. (I'm excluding inlined functions, which are present multiple times.)

Solution 2

A "header file" is actually inserted by the pre-processor before compilation starts. Just think of it as just "replacing" its #include directive.

The guard ...

#ifndef MY_HEADER_H
#define MY_HEADER_H

....

#endif

... is executed after the replacement. So, the header may actually be included multiple times, but the "guarded" part of the text is only passed to the compiler once by the preprocessor.

So, if there are any code-generation definitions in the header, they will - of course - be included into the object file of the compilation unit (aka "module"). If the same header is #includeded in multiple modules, these will appear multiple times.

For static definitions, this is no problem at all, as these will not be visible beyond the module (aka file scope). For program-global definitions, that is different and will result in "multiple definitions" error.

Note: this is mostly for C. For C++, there are significant differences, as classes, etc. add additional complexity to what/when multiple global objects are allowed.

Solution 3

A header file with appropriate include guards will be included only once per translation unit. Strictly speaking, it may be included multiple times, but the parts between the preprocessor #ifndef and #endif will be skipped on subsequent inclusions. If done correctly, this should be all (or most) of the file.

A translation unit usually corresponds to a "source file", although some obscure implementations may use a different definition. If a separately compiled source file includes the same header, the preprocessor has no way of knowing that another file had already included it, or that any other file was part of the same project.

Note that when you come to link together multiple source files (translation units) into a single binary, you may encounter problems with multiple definitions if the header does not consist only of declarations, templates, function definitions that are marked inline, or static variable definitions. To avoid this, you should declare functions in the header and define them in a separate source file, which you link together with your other source files.

Solution 4

The header file will be included once per translation unit, yes. It can be included multiple times per program, as each translation unit is handled separately for the compile process. They are brought together during the linking process to form a complete program.

Share:
17,679
Engineer999
Author by

Engineer999

Updated on June 03, 2022

Comments

  • Engineer999
    Engineer999 almost 2 years

    I know this is a common question but I still can't fully get my head around it.

    In a C or C++ program generated from multiple different source and header files, will each header file be only included once in the entire code when the header guards are used?

    Someone told me previously that a header file (with include guards) will get included only once in one translation unit but multiple times in the entire code. Is this true?

    If it gets included only once throughout the entire code, when one file wishes to include it and the preprocessor detects that it has already been included, how does that file that wishes to use it know whereabouts in the code it was previously included ?

  • dlavila
    dlavila almost 9 years
    you could also mention the non-standard #pragma once, it's worth knowing its existence
  • too honest for this site
    too honest for this site almost 9 years
    @dlavila: I did not for a purpose. One should not rely on it, so you have to ad the guards anyway. Also, this might defy libraries like boost which intentionally use multiple includes. (I'm not to always stick to the standard, but link-once has too little benefit and can cause much trouble).
  • dlavila
    dlavila almost 9 years
    is worth knowing its existence anyway, not as a replacement, but sometimes it can be very useful, e.g: if you are sure it's supported (SWE guys in your company told you that) and you are working in a project with thousands of headers (compilation time can be speed up a lot).
  • too honest for this site
    too honest for this site almost 9 years
    That is a special use-case and you will get to know that if required. However, it makes more sense to use precompiled headers and caches for this anyways. I will not add all possible alternative to the guard here, expecailly as that was actually not the question. The actual problem will not change a bit with this.
  • Engineer999
    Engineer999 almost 9 years
    What will happen if we have the function definitions in the header file. Won't there be many definitions of the same function throughout the program which is not allowed?
  • Engineer999
    Engineer999 almost 9 years
    In the case of C++, aren't we supposed to put template class and function definitions into the header file only. In that case won't there be multiple definitions of the same functions throughout the program which is not allowed?
  • Random832
    Random832 almost 9 years
    @Engineer999 Function definitions are not typically included in header files, except for inline functions
  • Engineer999
    Engineer999 almost 9 years
    Aren't functions implicitly inline if they are defined inside a class body in a header file (C++ of course) . How are the multiple definitions dealt with then?
  • too honest for this site
    too honest for this site almost 9 years
    @Engineer999: That's why I wrote my answer is mostly for C. It's some time ago when I programmed in C++, I just emember it is more complicated, e.g. with inline methods or constants - these are different from C. It is always problemeatic to cover these two languages with a single question. They are different languages. If you cannot extrapolate my answer, it might be a good idea to delete the C++-tag and ask again for C++ only.
  • Random832
    Random832 almost 9 years
    @Engineer999 Inline functions are designed not to cause problems when included multiple times - either they will not have a definition at all in the final output, or the linker will know to throw away all but one of them.
  • Bryan Shaw
    Bryan Shaw almost 9 years
    Excellent reply, but shouldn't you say "Generally, the header files only include declarations, not the actual implementations." since definitions are generally synonymous with implementations in c/c++?
  • Paul Draper
    Paul Draper over 5 years
    @BryanShaw, that has been fixed.
  • Chan Kim
    Chan Kim almost 4 years
    yes, this static declaration is important. in linux source there are many 'static inline' functions defined in the header files. even though they are used in multiple object files, it gives us no 'multiple definition' error during the linking process because of the 'static' nature.
  • xwa130
    xwa130 over 3 years
    Fantastic reply! Exactly what I'm look for!
  • sai
    sai about 3 years
    Excellent answer! Well explained, thanks!