Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

about include header file with guards

Tags:

c++

I am reading a book on Applied C++.

Include guards will prevent a header file from being included more than once during the compilation of source file. Your symbol names should be unique, and we recommend choosing the name based on the name of the file. For example, our file, cache.h contains this include guard.

#ifndef _cache_h_
 #define _cache_h_
 ...
 #endif // _cache_h_

Lakos describes using redundant include guards to speed up compilation. See [Lakos96]. For large projects, it takes times to open each file, only to find that the include guard symbol is already defined (i.e., the file has already been included). The effects on compilation time can be dramatic, and Lakos shows a possible 20x increase in compilation times when only standard include guards are used.

[Lakos96]: LargeScale C++ software design.

I don't have Lakos96 reference book to refer concept so asking help here.

My questions on above text is

  1. What does author mean by " For large projects, it takes times to open each file, only to find that the include guard symbol is already defined" ?

  2. What does author mean by "when standard include guards are used" ?

Thanks for your time and help.

like image 544
venkysmarty Avatar asked Jul 23 '13 08:07

venkysmarty


People also ask

What are guards in header files?

Header guards are designed to ensure that the contents of a given header file are not copied, more than once, into any single file to prevent duplicate definitions. This is a good thing because we often need to reference the contents of a given header from different project files.

What is an include guard in C?

include guard (plural include guards) (programming) In C and C++, a preprocessor directive used in header files to prevent them from being included multiple times.

What are header file guards in C++?

Header Guards in C++ are conditional compilation directives that help to avoid errors that arise when the same function or variable is defined more than once by the mistake of a programmer. According to C++, when a function or a variable is defined more than once, it yields an error.

How important is it to have an include guard for every header file?

Without a header guard, a code file could end up with multiple (identical) copies of a given type definition, which the compiler will flag as an error.


2 Answers

From C++ Coding Standards (Sutter, Alexandrescu)

Many modern C++ compilers recognize header guards automatically (see Item 24) and don't even open the same header twice. Some also offer precompiled headers, which help to ensure that often-used, seldom-changed headers will not be parsed often

So, I would consider those suggestions outdated (unless you are still using some very dated compiler).

As for your questions:

  1. it means: opening a file which is not needed (since it has been already included; which you will know because the include guard is already defined) is costy; and this might be an issue if you do it a lot of times (which can happen if you have hundreds of files in your project).
  2. as opposed to using non-redundant compile guards.

What is a redundant compile guard?

A naive compiler will reload the file every time it's included. To avoid that, put RedundantIncludeGuards around the include: header.h

 #ifndef HEADER_H_
  #define HEADER_H_
  // declarations
  #endif

foo.c

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

read more here. Your reference claims that by doing so you can be as much as 20% faster during compilation than you would be if foo.c were only doing

 #include "header.h"
like image 157
Stefano Falasca Avatar answered Oct 08 '22 22:10

Stefano Falasca


I don't know what Lakos96 says, but I'm going to guess anyway...

A standard include guard is like:

foo.h

#ifndef FOO_H_INCLUDED
#define FOO_H_INCLUDED
....
#endif

A redundant include guard is using the macro when including the file:

bar.c

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

That way the second time the foo.h file is included, the compiler will not even search for it in the disk. Hence the speedup: imagine a large project, one single compilation unit may include foo.h 100 times, but only the first one will be parsed. The other 99 times it will be searched for, opened, tokenized, discarded by the pre-compiler and closed.

But note that that was in 1996. Today, GCC, to give a well known example, has specific optimizations that recognize the include guard pattern and makes the redundant include guard, well..., redundant.

like image 7
rodrigo Avatar answered Oct 09 '22 00:10

rodrigo