c++visual-studioincludeinclude-guardstranslation-unit

How a multiple times #included guarded header file will be inside different translation units?


I know that #inclusion is often described as a text copy-pasting preprocessor directive. Now if a header is #include guarded, or #pragma onced, then how'd we describe what is actually happening past the first translation unit to #include said header?


Solution

  • There is no "first" translation unit. All translation units are conceptually translated in parallel (of course, in practice you might end up compiling them one at a time, but it doesn't matter).

    Each translation unit begins with a blank slate. Technically that isn't quite true because you can add #defines at the command line and there are some predefined macros as well, but anyway, no translation unit will have a "memory" of #defines that were executed in any other translation unit. Thus, a header may be #included multiple times despite the guards. It is just that it won't be #included multiple times into a single translation unit.

    This means that you must still take care to avoid multiple definitions: for example, if your header contains a global variable then you must ensure it is const (so it will have internal linkage) or explicitly declare it inline (to collapse all definitions into one) or extern (to suppress definition in the header so you can place the definition into a single translation unit).

    Despite the fact that include guards don't prevent multiple definitions across multiple translation units, they do prevent multiple definitions within a single translation unit, and this is important because even though some entities may be defined multiple times in a program, it's still not allowed for multiple definitions to appear in the same translation unit. For example, if you have an inline global variable in a header, then multiple translation units can include that header and the definitions will all be collapsed into a single definition at link time, but you will get a compilation error if any one translation unit defines that variable multiple times. Therefore, such a header must have an include guard.