-2

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 ?

5
  • What are you talking about? The macro name has always been completely arbitrary. Choose whatever you like. Other than the name, I see no difference between the three variants. However, I'd suggest refraining from names that begin with __ or with _+capital letter - these are reserved. Commented Nov 10, 2016 at 23:26
  • avoid beginning with underscore yours may interfere with system libraries Commented Nov 10, 2016 at 23:28
  • The macro names from those tutorials are not standard-compliant. Stick with what you were doing. Commented Nov 10, 2016 at 23:30
  • 1
    You can use whatever marco definition you like. There is also #pragma once, which is not standard, but is supported by virtually every C/C++ compiler. Commented Nov 10, 2016 at 23:33
  • eg if your macro: __WIN32 then a you are facing a collision Commented Nov 10, 2016 at 23:37

5 Answers 5

1

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.

Sign up to request clarification or add additional context in comments.

Comments

1

The #ifndef, #define, and #endif are the syntax parts that matter. What naming convention you use is up to you.

Comments

1

These are just names like variable names.

Double underscore names are reserved, so strictly speaking #define __A_H_INCLUDED__ is undefined behavior and underscore + capital letter shouldn't be used either.

You just want to avoid naming collisions with your other code and the standard and using the file name usually ensures that.

Comments

0
#define A_H

doesn't have any connection with file a.h.

Inside dir/filename.h, you can:

#ifndef WHATEVER_NOT_DEFINED_HENCE_HAVE_DIR_FILENAME_H_IS_GOOD_
#define WHATEVER_NOT_DEFINED_HENCE_HAVE_DIR_FILENAME_H_IS_GOOD_
#endif

but you can't use this

#define WHATEVER_HAS_DOUBLE_UNDERSCORE_LIKE_THIS_IS_BAD__
#define __OR_LIKE_THIS_IS_BAD
#define OR_LIKE__THIS_IS_BAD

and you can't have an identifer starts with undercore and followed by capital character like this:

#define _LIKE_THIS_IS_BAD

Comments

0

It comes down to personal/organizational preference although there are some conventions around this. In general it doesn't really matter what you put here as long as it's not used anywhere else.

Some examples:

  • A_H: Looks similar to a constant you would use in code.
  • A_H_: Would be better because you're not likely to see a constant with an underscore at the end.
  • _A_H_INCLUDED: At first blush this looks better because it's similar in appearance to a private file-scoped variable. But this is a problem because underscore + capital letter are reserved so this is not an appropriate macro.
  • A_H_INCLUDED: Without the leading underscore, clear purpose and not likely to conflict with anything else in your program.
  • __A_H_INCLUDED__: Double underscores are reserved; do not use.

Also, it's not part of the standard, but #PRAGMA ONCE is widely supported and accomplishes the same thing without needing to worry about naming conventions at all.

2 Comments

_A_H_INCLUDED Not better. Worse. Underscore followed by capital is reserved or use by the implementation. More here: What are the rules about using an underscore in a C++ identifier? Concept right though. The less likely to be accidentally repeated, the better.
The last two names are reserved for use by the implementation and should not be used in your code.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.