Does anyone use guarded include files

I'm in the process of learning C++ and I have a real world question about coding the .h include files.

In my reading the authors spent some time on using the
#ifdedf and #ifndef preprocessor directives to bracket the #include to prevent the file from being included multiple times in a compile. The consequence of multiple insertions of the include seemed to be more about wasted time and resources if I have correctly understood.

My question is: Is it important to bracket #include directives to prevent a file from being included multiple times or is this more an academic concern that is not important in the real world? Example follows:

// Example of guarded include file

#ifndef exampleInclude                      // test to see if the include has already happened
    #define exampleInclude                 // define the item so later tests fail
    #include <exampleInclude>          // include the file
#endif

// Rinse and repeat for all include files

It's important for header writers, not for those that use them. The guards go inside the include-file. The example posted is "inside-out".

Suppose you have two unrelated things to use. Both use JSON for configuration. One function is

void fish(JsonDocument config);

and the other

void cutBait(JsonDocument config);

Your code has

#include <fish.h>
#include <bait.h>

Because JsonDocument is part of the signature, at the top of both of those files is

#include <ArduinoJson.h>

The first non-comment line in that file (for v7 at least) is

#pragma once

once generally works by asking the compiler to remember that specific file on disk, and if it is included again, to simply skip it. (This means that if you have the same file in two places, the compiler can consider them to be different, and once would not work. But that also means that when searching for the file by name alone, it would not consistently find the same one, which means something screwy with the search path, and all bets are off.)

The old-style guards, as in the example, wrap the entire content of the header: everything it declares, defines, and includes. You have to come up with a name, and there's a small chance there's a collision with something else using the same name.

Unless there's a specific reason to exclude it, I'd put #pragma once at the top of every header. With a slightly complex project, you could have a common type that is used by separate things, and run into the same problem as JSON in my example above.

1 Like

No, not at all. The guards reside in the header files themselves.

That #include line is not found in the header file, instead it occurs in any file that needs definitions imported from the header file. In the header file itself you'll find all definitions in the place of that line.

So It's up to the header file writer, not up to the user, to prevent an header file from multiple includes.

True, but I think it looks better aesthetically. I prefer the format of the first code below to the second. In a complex header file, having the guards first means I don't need to go searching for where they start:
This:

#ifndef GUARD
#define GUARD

#include <header1>
#include <header2>
  .
  .
#include <headerN>
  .
  .
Everything else in Header File Here
  .
  .
#endif

Verses This:

#include <header1>
#include <header2>
  .
  .
#include <headerN>
#ifndef GUARD
#define GUARD
  .
  .
Everything else in Header File Here
  .
  .
#endif

while this is way beyond the scope of things done on this forum, there is a difference between putting the guard in the header file rather that in the file with the #include

the complete .h file is read when the guards are inside the .h and of course the content of the file between the #ifndef and #endif is ignored (i.e. typically all of the file).

now consider a very large projects (e.g. CAD) where .h files are included many times and their content ignored many times. In such projects, putting the guards in the file with the #include avoids reading the file and in such projects can significantly decrease the build time.

The header file is read on its first appearance. Afterwards the compiler knows that the file is guarded and does not try to open it any more.

1 Like

I would like to thank everyone for the time invested and the detail of the responses. While it may be more detailed than could reasonably be expected it was precisely what I needed. I am learning C++ and want the results to be the best I can make them. I grew up on machines where 8 or 16 K memory was standard and 32K was huge. In many ways the Arduino is a return home where code efficiency is required and elegance is rewarded.

You have all been of great help in explaining not only how but why a practice is preferred.
-Glenn

you're saying that the pre-processor remembers that a particular header has guards when that file is included in other nested .h files?

In the C/C++ each translation units compiles independently, so in "very large projects" most of the inclusions will come from multiple inclusions of headers in the internal project .cpp files. Therefore, using conditional inclusion of a header in one user file ( Arduino sketch ?) has very little impact on compilation time.

I think that the answer that OP marked as a solution is actually not entirely correct.
It is standard practice to place guards within the headers themselves, rather than around their inclusion in other files. The second option is exotic, and I don’t think it provides any advantages.

1 Like

not sure what this is saying. of course a .h can be conditionally included based on the condition of the #if.

but if the guard is inside the .h, the ,h file needs to be entirely read while if the guard is in the file with the #include it does not.

this is from a book i read on very large applications from 20 years ago where the author said it would take several days to recompile their entire application ... at that time.

in a very large project, the same .h files could be read dozens of times for each .cpp. dozens of .h files read dozens of times in 100s of .cpp file would have an impact on total build time

That's why the style of the "CAD" project was to put the guard in the file with the #include

To gave this strategy a little chance to success, you need to put guards in EACH file and each place where #include used.

So if you have a some base definitions in base.h file, included in 100 .cpp files - you will need to write a 100 guards using your way of placing guards and only one if you put the guard to the header itself.

yes!

and completely useless, because the file will still be included 100 times

the .h will only be read the first time the #ifndef condition is true, avoiding all subsequent reads when the .h is included in other .h files

Let me clarify to be sure I have this correctly:

(1) If one uses a preprocessor directive #ifndef in the invoking sketch then the file is only used once and there is minimum compiler overhead. This requires each use of the #include to be guarded in all invoking sketches.

(2) If one uses a preprocessor directive #ifndef in the actual file (.h, .cpp, etc.) then the file is opened and read by the preprocessor each encounter. The actual include file is only inserted once in the compile. The solution is not as efficient as #1 because the included file is opened each time but is more efficient than doing nothing because it is only compiled once.

(3) If one uses the #pragma once preprocessor directive in the actual file then the file is only opened once. This seems to be the most efficient solution because it prevents the open (like solution 1) but does not require insertion of guarding code into all invoking programs. The down side is that #pragma once may not be compatible with all implementations of the C++ compiler.

Have I gotten this right??

My conclusion is the the #pragma once solution is the easiest to implement and provides the same compile-time benefit as any other solution. Since I'm writing for the Arduino IDE the possibility that some (very old?) implementations of the compiler will fail is not important to me.

Solution 1 and 3 are equivalent. If a compiler can flag a file for #pragma once inclusion it can use the same flag if it detects the guard inside that file.

A C/C++ compiler is said to spend 50% of its time in source code parsing.

Additionally, "large" projects are rarely compiled in their entirety during a build. Thanks to the magic of makefiles, a file only gets recompiled if it or its include files are modified.

you'd have to ask the author that i read this from. at that time, i thought he said it took 5 days to completely rebuild the code

That may be an option, if the guard was detected and remembered in the first read of the file. If not remembered, how should the compiler know that the file contains a guard?

Skipping a file is an option only before the file is opened. Once the file is open it has to be processed until its end.

you didn't read the earlier comments where i said this was for a very large application, i believe CAD.

and while you may be correct in believing such an application wouldn't take as long to build, systems have evolved to allow such large projects that couldn't be done in the past.

i only brought this up as an example of why you would put the "guard" in the file including the .h rather than the .h file. it is clearly an exceptional case