code code - 27 days ago 7
C++ Question

C++ header guard syntax

For a file name a.h... I've always used

#ifndef A_H
#define A_H
#endif


but now I see in tutorials

#ifndef __A_H_INCLUDED__
#define __A_H_INCLUDED__
#endif


and also

#ifndef _A_H_INCLUDED
#define _A_H_INCLUDED
#endif


So I was wondering what's going on... Has this changed in never versions of C++ or is this compiler dependent?

I use MinGw (gnu gcc g++) and msvc...

Edit:

In case there is confusion as to why this is asked, I believe that this is quite confusing to novices. For example, for a file named a.h we don't say

#ifndef a.h
#define a.h


or even

#ifndef A_H
#define A_H a.h


that would make sense to me.

instead we say A_H... or one of the variants above. Therefore, I would think not just any syntax is ok. I always used to think that it has to be the file name in caps and that the period has to be replaced with an _. This is how I saw it being taught for years. No I see words like _INCLUDED ... which are obviously not part of the a.h file name in any way... this is confusing... how does the compiler reconcile that A_H_INCLUDED refers to a.h? I don't see why this is down voted I think it's quite confusing.

Also, one person has stated that some of these variants are not standards compliant, therefore I think it is a valid question and should not be down voted.

Or is it the case that #define A_H dumps all the code from the header file into the A_H macro? But I thought that define ends at new line character... in which case we define A_H with no value. In that case A_H is just a name with no value and the question remains how does the compiler know you're talking about file a.h when you use a funky empty marco variable like A_H_DINGDONG ?

Answer

There's been no relevant change in the language. The identifier used in an include guard is just an identifier. In fact the entire include guard mechanism is not defined by the language; it's just a convention.

The issue is that identifiers starting with two underscores, or with one underscore and an uppercase letter, are reserved to the implementation. That means that if you use the name __FOO_H__ in your code, it's at least possible that the compiler has already predefined it for its own internal purposes, and your code could break in some undetermined manner.

Tutorials that tell you to write:

#ifndef __A_H_INCLUDED__ 
#define __A_H_INCLUDED__ 
#endif

are giving you poor advice.

One more subtlety: macro names starting with E and a digit, or E and an uppercase letter, are reserved for use in the <errno.h> / <cerror> header. So if your header file is called earth.h and you write:

#ifndef EARTH_H
#define EARTH_H
#endif

then you could in principle collide with an EARTH_H error number.

That's not likely to happen, and the _H suffix is almost certainly enough to prevent it, but a convention I use to avoid it altogether is:

#ifndef H_EARTH
#define H_EARTH
#endif

You suggest:

#define a.h

A macro name must be a single identifier. That actually defines the macro a with the value .h.

#define A_H a.h

Since the macro is only tested using #ifndef, it doesn't matter at all what value it has, only whether it's defined or not.