4

I am new to writing my own headers, but due to necessity, I must learn.

I am writing a header, and I'm trying to grok header guards. Is there a difference between having one or two underscores before and after the included header file?

Take this hypothetical example: x.h

//x.h
#ifndef __X_H_INCLUDED__
#define __X_H_INCLUDED__
//functions n stuff
#endif

versus:

//x.h
#ifndef _X_H_INCLUDED_
#define _X_H_INCLUDED_
//functions n stuff
#endif

Is one more or less right than the other? Is there a difference?

Brick
  • 3,475
  • 7
  • 21
  • 43
j0h
  • 1,401
  • 2
  • 21
  • 41
  • 4
    double underscores are reserved to the implementation -- using them in your own header files is undefined behavior and generally not a good idea. – Chris Dodd Oct 08 '15 at 02:27
  • Also check out `#pragma once` http://stackoverflow.com/questions/1143936/pragma-once-vs-include-guards – Anthony Oct 08 '15 at 02:32
  • 2
    It [seems like](http://stackoverflow.com/a/33005607/4143855) having no leading underscores would be best. Why not just `X_H_INCLUDED` ? – Tas Oct 08 '15 at 02:32
  • 1
    @Anthony, pragmas are, by their very definition, non-portable. Though, of course, that's not an issue if you're happy to limit yourself to compilers that support it (I suspect that may be quite a few: https://en.wikipedia.org/wiki/Pragma_once#Portability). – paxdiablo Oct 08 '15 at 02:38
  • @paxdiablo As per the linked question, quite a few. I usually use both `#pragma once` and include guards. – Anthony Oct 08 '15 at 02:40

3 Answers3

8

As per C++11 17.6.4.3.2 Global names (though this restriction has been around for a while):

Certain sets of names and function signatures are always reserved to the implementation:

  • Each name that contains a double underscore _ _ or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use.
  • Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace.

So you really should be using neither if you want your software to be portable though, having said that, plenty of people do use both varieties.

It would be "safer" to use something like GUARD_X_H or X_H_INCLUDED though, of course, you still need to be wary of clashes. You might take the Java way and end up with macros like:

AU_COM_POWERFIELD_DATASTRUCTURES_TREES_BALANCED_BTREE_H

as long as you stay below the implementation limits for macro names (which, from memory, is at least 1024 characters).

Alternatively, if you want to sacrifice portability (but not much portability since it's supported in a great many compilers), you could look into #pragma once, where you don't have to worry about coming up with unique names.

Community
  • 1
  • 1
paxdiablo
  • 772,407
  • 210
  • 1,477
  • 1,841
2

From the 2003 C++ Standard (these rules still apply):

17.4.3.2.1 Global names [lib.global.names]

Certain sets of names and function signatures are always reserved to the implementation:

Each name that contains a double underscore (_ _) or begins with an underscore followed by an uppercase letter (2.11) is reserved to the implementation for any use. Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace.165 165) Such names are also reserved in namespace ::std (17.4.3.1).

shafeen
  • 2,060
  • 14
  • 20
1

I like to follow a particular structure for include guards which matches the structure of the project.

#ifndef PROJECT_PATH_TO_FILE_HPP
// etc. etc.

So if the project is names "skittles", and the path to the header is taste/the/rainbow.hpp then my include guard becomes:

#ifndef SKITTLES_TASTE_THE_RAINBOW_HPP
// etc. etc.

This works pretty well, you just have to be wary of name clashes with file names and directories. For example, one file in the project root called foo_bar.hpp, and one at foo/bar.hpp. This will cause a name clash which would have to be worked around.

Another option is to use namespaces instead of paths:

#define PROJECT_NAMESPACE_MODULE_HPP

I've also seen people append the date and time the file was created, or use a UUID, to add further safety against name clashes.

Anthony
  • 11,352
  • 9
  • 65
  • 100