What is the conventional way of writing include guards?
Asked Answered
N

2

11

I usually write them as (for example.h):

#ifndef _EXAMPLE_H_
#define _EXAMPLE_H_
#include "example.h"
#endif

Does underscore convention matter? I've seen conflicting information when I googled this. Does the _EXAMPLE_H_ even have to match the name of the header?

Neglect answered 25/6, 2013 at 21:6 Comment(4)
I believe this has already been thoroughly covered, here.Gyroscope
Or better yet, if you are looking for more extensive coverage of the topic consider google-styleguide.googlecode.com/svn/trunk/… . You can also read google style guide, just as a referenceWraparound
The other is for C++, which a programming language distinct from C. The conventions are similar - for now - however, but the justification differs.Hallucinosis
Strongly related: https://mcmap.net/q/122048/-what-is-the-recommended-naming-convention-for-include-guards/5740428Stertor
U
18
Does underscore convention matter?

Yes. It matters.

Identifiers with a leading underscore followed upper case letter is reserved for implementation. So what you have would cause undefined behaviour.

The following is the C standard's specification for naming the identifiers (C11 draft):

7.1.3 Reserved identifiers

Each header declares or defines all identifiers listed in its associated subclause, and optionally declares or defines identifiers listed in its associated future library directions subclause and identifiers which are always reserved either for any use or for use as file scope identifiers.

— All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use.

— All identifiers that begin with an underscore are always reserved for use as identifiers with file scope in both the ordinary and tag name spaces.

— Each macro name in any of the following subclauses (including the future library directions) is reserved for use as specified if any of its associated headers is included; unless explicitly stated otherwise (see 7.1.4). — All identifiers with external linkage in any of the following subclauses (including the future library directions) and errno are always reserved for use as identifiers with external linkage.184) — Each identifier with file scope listed in any of the following subclauses (including the future library directions) is reserved for use as a macro name and as an identifier with file scope in the same name space if any of its associated headers is included.

No other identifiers are reserved. If the program declares or defines an identifier in a context in which it is reserved (other than as allowed by 7.1.4), or defines a reserved identifier as a macro name, the behavior is undefined.

If the program removes (with #undef) any macro definition of an identifier in the first group listed above, the behavior is undefined.

Without violating any of the above, the include guard name can be anything and doesn't have to be the name of the header file. But usually the convention I have seen/used is to use same name as that of the header file name so that it doesn't cause any unnecessary confusion.

Upstairs answered 25/6, 2013 at 21:24 Comment(1)
One common convention is to map the header name to uppercase and replace .h by _H, so the guard for foobar.h would be FOOBAR_H. If the name starts with 'e', for example "elvis.h", then the guard macro would be ELVIS_H -- and macros starting with E and a digit or uppercase letter are reserved for use by <errno.h>. It's vanishingly unlikely that an implementation will define ELVIS_H as an error code, but you can avoid the possibility by using a convention like H_HEADER_NAME rather than HEADER_NAME_H.Properly
M
-2

There is no absolute requirement as to how include guards are named. It does not have to match the header name. I have seen (and used myself) some that use a UUID, basically composed of a randomly generated hexadecimal string.

Technically as KingsIndian said, identifiers beginning with underscores are reserved:

The rules, paraphrased from ANSI Sec. 4.1.2.1, are:

1. All identifiers beginning with an underscore followed
   by an upper-case letter or another underscore are always
   reserved (all scopes, all namespaces).
2. All identifiers beginning with an underscore are reserved
   for ordinary identifiers (functions, variables, typedefs, enumeration
   constants) with file scope.
...

comp.lang.c FAQ list · Question 1.29

Maybe the new ISO C11 (?) standard relaxes these rules, but that's been the bottom line for a while.

Magellan answered 25/6, 2013 at 22:58 Comment(4)
-1. That's not the rule about underscores. And if you don't start with an underscore but use an UUID, you're likely to start with a numeral.Effector
Not a raw UUID but something like INCLUDED_AF3430340AB3012FE0DEADBEEF.Magellan
Identifiers starting with an underscore followed by either a second underscore or an uppercase letter are reserved for any use. All identifiers starting with an underscore are reserved for use as identifiers with file scope in both the ordinary and tag name spaces. It's good to know the exact rules, but it's wise to be conservative and just avoid defining anything starting with an underscore.Properly
No, ISO C11 has not relaxed the rules.Properly

© 2022 - 2024 — McMap. All rights reserved.