Internal vs External Include Guards

2.6k views Asked by At

I've heard that you should prefer writing internal include guards instead of external include guards.
I have searched around the internet but haven't found an answer to it.

This is a snippet of the book C++ Coding Standards by Herb & Andrei that shows an "external include guard":

Avoid using the obsolete external include guards advocated in older books:

#ifndef FOO_HJNCLUDED_ //NOT recommended
#include "foo.h"
#define FOO_HJNCLUDED_
#endif

Now, this leads to the question below:

Q: What is an internal include guard and what is an external include guard? What's the difference between the two, and why is internal include guards preferred?
I would like that the answer also provide an example.

Edit: I ended up answering my own question.

2

There are 2 answers

10
André Caron On BEST ANSWER

Here's something I've seen that probably explains the comment.

Here, foo.h is defining an "internal include guard" (shortened to simply "include guard" by most people since it's the traditional way of doing it).

// foo.h
#ifndef _FOO_H__
#define _FOO_H__

// ...

#endif  // _FOO_H__

In contrast, bar.h is using foo.h's include guard outside of foo.h. We can nickname this as an "external include guard".

// bar.h
#ifndef _BAR_H__
#define _BAR_H__

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

// ...

#endif  // _BAR_H__

One (very large) project I worked on claimed that this increased compiling speed, but the claim is dubious as this seems to me like a trivial compiler optimization and I haven't seen any metrics to prove the claim. However, we did notice it was annoying to read when including multiple header files.

2
Andreas DM On

After a good digging around, I can now answer my own question.

Internal Include Guard:

The common idiom putting "include guards" around the content of header files being included:

header.h

#ifndef HEADER_H
#define HEADER_H

// Contents of include file

#endif

Therefore, the content of the header will be processed once even though the header is #includeed multiple times.
This is known as an "internal include guard" because the guard is entirely internal to the header file.


External Include Guard:

However, there could be an issue with the above method if the compiler takes a simple approach, opening the file multiple times to check for "internal include guards" which could cause increased compile time in large projects.

header2.h

#ifndef HEADER_H
#include "header.h"
#endif

// Rest of header file goes here

The line: #ifndef HEADER_H is still defined and checked internally in header.h. But by checking it externally the compiler might avoid having to open the file at all.
It is only suggested to check externally when a header file is included from other header files.
The check is not necessary when included from a source file.


Conclusion:

  • Internal guard guarantees correctness
  • External guard may improve speed of compilation on some compilers
    • The cost involved is that of putting the check everywhere a header file is #included in another header file, and spelling the name of the guard symbol correctly. Therefore not preferred.