What is #ifndef QT_H for???
-
I am currently working my way into an older codebase, and in a lot of header files, I see things like this:
#ifndef QT_H #include <QString> #include <QVector> #include <QDomDocument> #include <QMap> ... and other Qt includes ... #endif
I am wondering why the
#ifndef QT_H
check is necessary. I tried googling for this, but could not find anything related to it. I did find this same construct in other code on the net, which makes me assume that it is or was a common thing to do. Is this something that used to be necessary for older code, but is deprecated nowadays? If anybody can provide me a link or book where this is explained, that would be very nice.Regards,
Bart -
@Bart_Vandewoestyne
That looks to me like a home-brewed method to reduce a bunch includes. IIRC it does not come from Qt.
Most likely at the end of such a block QT_H is defined. If you include 10 different of your includes holding this, you make sure that the Qt headers are only included once instead of the reducndant 9 times in addition.Some people do it this way and put a lot of not required includes in their code and wonder why the compilation respectively the screening takes so long. This is than a counter measure.
In my opinion it is better to think about the includes you really need.
-
Hi and welcome to devnet,
in C/C++ the synatx
// my_header.h #ifndef XXXX #define XXXX ...... #endif
is called include guard; is a standard pattern to avoid multiple inclusion in the same source file.
As @koahnig saidQT_H
is not defined in Qt but is something the developer self-made.NOTE: in modern C++ compilers you can achieve the same results using
#pragma once
// my_header.h # pragma once ....
-
I think I've finally discovered the reason for these include guards. I think they are so-called "Redundant Include Guards" (sometimes also called "External Include Guards"), as discussed in Section 2.5 in "Large Scale C++ Software Design" by John Lakos. In that book on page 85, Lakos introduces the following 'Minor Design Rule':
Place a redundant (external) include guard around each preprocessor include directive in every header file.
For as far as I understand the book, this design rule exists mainly to reduce compilation times (preprocessor time actually...), but I would assume that nowadays, most development environments are smart enough to keep track of previously included headers files, which makes the design rule outdated.
My educated guess is thus that removing these redundant include guards will not change anything to the program, it might only have an effect on the compilation (preprocessing) time.
-
@Bart_Vandewoestyne said in What is #ifndef QT_H for???:
but I would assume that nowadays, most development environments are smart enough to keep track of previously included headers files, which makes the design rule outdated.
Why would you assume that? The preprocessor cares not about redundancy if you don't force it to (either by adding a
#pragma
or an include guard). Something more, your code may be structured in such a way that redundant includes are needed, although this would be a bad design by itself. In any case the preprocessor is a pretty basic copy-paste machinery, it cares only for a handful of statements and about its simple syntax, not about the semantics. -
@kshegunov said in What is #ifndef QT_H for???:
Why would you assume that?
There are several reasons why I'm assuming that current compilers have the so-called include guard optimisation:
-
In his book (first published in 1996), Lakos writes "Note that some development environments are smart enough to keep track of previously included header files, but many common environments are not." Being more than 20 years later now, my educated guess is that most development environments have caught up and are smart enough.
-
There is a Stack Overflow post that indicates that redundant include guards are pointless for MSVC and GCC: http://stackoverflow.com/questions/1021357/wrapping-includes-in-ifndefs-adds-any-value
-
The online gcc docs have a specific page where it is mentioned that CPP (being the C preprocessor) does not bother to rescan a file if it is already included: https://gcc.gnu.org/onlinedocs/cpp/Once-Only-Headers.html
-
I've found an interesting blogpost about the topic and it even provides code to test your compiler for include guard optimization: http://bobarcher.org/software/include/index.html The results are here.
The preprocessor cares not about redundancy if you don't force it to (either by adding a
#pragma
or an include guard). Something more, your code may be structured in such a way that redundant includes are needed, although this would be a bad design by itself. In any case the preprocessor is a pretty basic copy-paste machinery, it cares only for a handful of statements and about its simple syntax, not about the semantics.After having done some online research, I think I don't agree with the above. At least GCC's preprocessor does seem to have the so-called include guard optimization. Furthermore, redundant include guards are a technique introduced to speed up compilation (by avoiding the unnecessary re-opening of include files). I cannot imagine a situation where they would be needed for other reasons than for speeding up compilation. If you do not use them, the only consequence is that your compilation speed might go down.
-
-
@Bart_Vandewoestyne said in What is #ifndef QT_H for???:
At least GCC's preprocessor does seem to have the so-called include guard optimization.
Yes, it seems it does. I wonder what would happen if you have stuff after the
#endif
though ...
My point was rather that the preprocessor doesn't care about the contents in the ifdef block, so apparently GCC just optimizes out the file reading (i.e. finding the#endif
and skipping the contents) as it already knows the header contains it. I still maintain that "keeping track of previously included headers files" is somewhat different from "include guard optimisation", as the latter implies a specific case - when there's include guard wrapping the whole of the header.I cannot imagine a situation where they would be needed for other reasons than for speeding up compilation.
Me neither, so I don't use redundand guards.
If you do not use them, the only consequence is that your compilation speed might go down.
I'd go a step further and say that only your preprocessing time will be longer, the compiler runs after the preprocessor and has no notion of
#ifdef
s and the like. From its point of view nothing will have changed either way.