Using #pragma once with conditional compilation

The #pragma once directive offers some advantages over the traditional header guard idiom, but as it is not part of the C/C++ standard we have to rely on the – not too verbose – compiler documentations. In this post, I examine what happens if you mix this directive with other preprocessor directives and conditional compilation.

C/C++ programs are separated to header (.h, .hpp) and source (.c, .cc, .cpp) files and header files are usually included from one or more header and source files. Care must be taken to avoid redefinitions of types and preprocessor directives. Every programmer knows how to use header guards as the only standard way of doing this.

The #pragma once directive is a newer method for this purpose that offers superior compiler performance because the compiler won’t have to read and preprocess the header file again. Other benefits include improved code readibility, less errors introduced by moving or renaming header files, and no cluttering of preprocessor namespace. Although it’s not included in the standard, all major C/C++ compilers already support it. GCC and Clang claim that they are able to detect the header guard idiom and offer the same performance as #pragma once making it unnecessary. On the other hand, Visual Studio encourages the usage of this directive over the header guards.

However, one aspect is not covered well in any of the compilers’ documentation, namely what happens if we not follow the traditional header guard idiom and mix #pragma once with conditional compilation. So I did a little test to find out how do they work if I put the directive in the middle of a header file instead of the beginning.

I’ve created the following header file that contains alternating code depending on a value of a preprocessor define. Only one path contains the #pragma once directive. The #pragma message lines are pleaceholders for the actual source code, se will be able to clearly see which lines are processed from the compiler output.

// a.h
#ifdef HEAD
# pragma message ("Head included")
#else
# pragma once
# pragma message ("Body included")
#endif

To test it, I have prepared a source file that includes the header file multiple times with different values for the preprocessor define controlling the header file. Similarly to the other file, I’ve put #pragma message directives to have more sensible output from the compiler.

// a.c
#define HEAD
# pragma message ("Including head")
# include "a.h"
# pragma message ("Including head")
# include "a.h"
#undef HEAD

#pragma message ("Including body")
#include "a.h"
#pragma message ("Including body")
#include "a.h"

#define HEAD
# pragma message ("Including head")
# include "a.h"
#undef HEAD

I’ve compiled these files with various compilers (Clang 3.4, GCC 4.8.3 and MSVC 18) and all worked as expected. I include only the MSVC output as it’s the most readable, but all compilers behaved the same way:

a.c
Including head
Head included
Including head
Head included
Including body
Body included
Including body
Including head

If we include only the first part of the header file (HEAD defined) it is possible to include it many times, but as soon as the second part is included (and #param once is read by the preprocessor) it will never be included again (regardless of whether the HEAD macro is defined or not).

Leave a Reply

Your email address will not be published. Required fields are marked *

*