jayjyli
jayjyli

Reputation: 821

#ifndef syntax for include guards in C++

I'm currently studying for a CS course's final exam and I've run into a minor (maybe major?) issue regarding the syntax of C++ #ifndef.

I've looked at the syntax for #infndef when using it as an #include guard, and most on the web seem to say:

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

But my class's tutorial slides show examples as:

#ifndef __HEADER_H__
#define "header.h"
...
#endif

I was wondering what (if any) the difference was between the two. The exam will most likely ask me to write an #include guard, and I know conventional wisdom is to just go with what the prof / tutor says, but if there's a difference during compilation I'd like to know.

Upvotes: 10

Views: 17134

Answers (5)

Gabriel Staples
Gabriel Staples

Reputation: 52687

I recommend #pragma once over #ifndef.

Ex:

#pragma once

// Rest of header file contents go here

Many compilers now support this (including GCC, LLVM/clang, and Microsoft), and it's easier to maintain, faster to compile, and less error-prone.


As I also state in my answer here, GCC's official documentation states: https://gcc.gnu.org/onlinedocs/cpp/Pragmas.html:

#pragma once

If #pragma once is seen when scanning a header file, that file will never be read again, no matter what. It is a less-portable alternative to using #ifndef to guard the contents of header files against multiple inclusions.

And Microsoft also strongly supports its use: https://learn.microsoft.com/en-us/cpp/preprocessor/once?view=msvc-170

once pragma

Specifies that the compiler includes the header file only once, when compiling a source code file.

...

The use of #pragma once can reduce build times, as the compiler won't open and read the file again after the first #include of the file in the translation unit. It's called the multiple-include optimization.

(emphasis added):

We recommend the #pragma once directive for new code because it doesn't pollute the global namespace with a preprocessor symbol. It requires less typing, it's less distracting, and it can't cause symbol collisions. Symbol collisions are errors caused when different header files use the same preprocessor symbol as the guard value. It isn't part of the C++ Standard, but it's implemented portably by several common compilers.

Upvotes: 2

Marc
Marc

Reputation: 16512

There's no difference if you don't use underscore in variable names anywhere else, it's only a naming convention.

You just need to put something unique.

Upvotes: -1

Keith Thompson
Keith Thompson

Reputation: 263267

An argument for putting the include guards in the file that includes the header, rather than in the header itself, is that if the file has already been included the compiler (specifically the preprocessor) doesn't have to open and read the include file again.

That's a weak argument. In practice, the time saved is trivial, and the potential for error is large.

In your example:

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

you don't show us the #define HEADER_H. Is it somewhere in header.h? If so, how do you know that the author of header.h chose to use HEADER_H as the name of the include guard macro? What if it changes to something else later?

If you decide to put the include guard in the including file, you should define the macro there as well:

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

But, as other answers have already said, it's much better to put the guard in the header itself:

header.h :

#ifndef HEADER_H
#define HEADER_H
/* contents of header.h */
#endif

and then the include simply has:

#include "header.h"

and has one less piece of information to worry about.

Upvotes: 2

Oliver Charlesworth
Oliver Charlesworth

Reputation: 272507

The usual practice is to do neither, and put the include guard inside the header file, as it reduces repetition. e.g.:

header.h

#ifndef HEADER_H
#define HEADER_H

// Rest of header file contents go here

#endif

Precisely what you use as the macro name is down to your particular coding standard. However, there are various subtle rules in the C and C++ standards that prevent you from using identifiers beginning with underscores,1 so you should avoid __HEADER_H__, just to be on the safe side.

It's also worth mentioning that you should pick something that's unlikely to clash with anything else in your codebase. For example, if you happened to have a variable called HEADER_H elsewhere (unlikely, I realise), then you'd end up with some infuriating errors.


1. See e.g. section 7.1.3 of the C99 standard.

Upvotes: 21

juanchopanza
juanchopanza

Reputation: 227418

Names starting with a double underscore are reserved for the implementation, so I would advise against using __SOMETHING in your include guards. Also, try to chose names that make clashes unlikely. So it seems your class' tutorials are wrong on at least two counts. See this humorous article for example.

Upvotes: 5

Related Questions