views:

344

answers:

3

Are 'redundant include guards' necessary in Codegear RAD Studio 2009? Is the compiler smart enough to deal with this on it's own?

For example, I might have the following 'include guard' in foo.h:

#ifndef fooH
#define fooH
// ... declaration here
#endif

and the following 'redundant include guard' in use_foo.h:

#ifndef fooH
    #include "foo.h"
#endif

Additionally, if the compiler is not smart enough, are 'redundant include guards' necesarry if they are being included in a source file. e.g. use_foo.cpp. ?

+2  A: 

The "redundant include guard", as you call it, speeds up compilation.

Without the redundant guard, the compiler will iterate the entire foo.h file, looking for some code that might be outside the #ifndef block. If it's a long file, and this is done many places, the compiler might waste a lot of time. But with the redundant guard, it can skip the entire #include statement and not even reopen that file.

Of course, you'd have to experiment and see the actual amount of time wasted by the compiler iterating through foo.h and not actually compiling anything; and perhaps modern compilers actually look for this pattern and automatically know not to bother opening the file at all, I don't know.

(Begin edit by 280Z28)

The following header structure is recognized by at least GCC and MSVC. Using this pattern negates virtually all benefits you could gain with guards in the including files. Note that comments are ignored when the compiler examines the structure.

// GCC will recognize this structure and not reopen the file
#ifndef SOMEHEADER_H_INCLUDED
#define SOMEHEADER_H_INCLUDED

// Visual C++ uses #pragma once to mark headers that shouldn't be reopened
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#   pragma once
#endif

// header text goes here.

#endif

(End edit)

Ricket
@Ricket: Yes, at least a few compilers know about include guards, won't even open a file when its included guard is already defined.
Jerry Coffin
@Ricket: *At least* GCC and MSVC can handle includes without reopening the file. I'm going to edit your post to show exactly which header is recognized by these two compilers. :)
280Z28
@280z28: is it necessary to have the compiler guards there? I thought the preprocessor just ignores the `pragma once` directive if it doesn't recognise it?
Seth
@Seth: http://www.keil.com/support/docs/887.htm
280Z28
@Seth:no, the compiler guards aren't *necessary*, but a fair number of compilers give a warning if they encounter an unrecognized pragma.
Jerry Coffin
@280Z28: Very nice! Can you provide a source of this information? Just to give it full credibility, not that I doubt it at all.
Ricket
@Ricket: I pulled the code from one of my own projects (but added the comments for here).
280Z28
@280Z28: I mean, how are you certain that GCC and MSVC recognize the structure? I imagine it is the case but do you know where there is official documentation that says so?
Ricket
+3  A: 

These redundant include guards are intended to emulate the functionality of the proposed #pragma once directive: if some header file has already been included, then the preprocessor will not even attempt to locate, open and parse it anymore (as it would have to with the "ordinary" include guard technique). In many cases this makes handling of include files much more efficient (speeds up compilation).

This approach is obviously a high-maintenance one: one has to make sure that the spelling of the guard symbol is exactly the same inside the header file as well as outside.

AndreyT
+1  A: 

The portion of the code you marked as "redundant include guard" is not necessary but it is a possible optimization.

In the case of C++Builder, there is logic to detect header guards, so it should not be necessary.

In the general case, the preprocessing pass is usually pretty fast anyhow, so it's unlikely that this optimisation would buy you much anyhow.

David Dean - Embarcadero