Naming Include Guards

Naming Include Guards

From my own experience, the convention is to name the inclusion guards after the header file containing them with the exception that the name is all in caps and the period is replaced with an underscore.

So test.h becomes TEST_H.

Real life examples of this include Qt Creator, which follows this convention when auto-generating class header files.

Names used for include guards?

To pick a good name for a header guard, consider these points:

1) the name has to be unique, so make it long and specific. That can usually be accomplished by including things like project name, module name, file name and file extension.

2) make sure you don't use names reserved for the implementation. So, names starting with underscore followed by a capital letter are out, as are names containing double underscore, names ending in _t and a few more.

3) make the name make sense to human readers. So don't just generate a UUID and use that.

4) convention dictates that you use all uppercase for macros to distinguish them from ordinary variables.

Underscores are not needed, as such, but since you cannot use spaces in macro names, underscores serve as a good alternative to keep things readable.

So, IMHO, a good guard name for a file foo.h in a submodule bar inside project baz is: BAZ_BAR_FOO_H .

Include guard conventions in C

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.

about include header file with guards

From C++ Coding Standards (Sutter, Alexandrescu)

Many modern C++ compilers recognize header guards automatically (see
Item 24) and don't even open the same header twice. Some also offer
precompiled headers, which help to ensure that often-used,
seldom-changed headers will not be parsed often

So, I would consider those suggestions outdated (unless you are still using some very dated compiler).

As for your questions:

  1. it means: opening a file which is not needed (since it has been already included; which you will know because the include guard is already defined) is costy; and this might be an issue if you do it a lot of times (which can happen if you have hundreds of files in your project).
  2. as opposed to using non-redundant compile guards.

What is a redundant compile guard?

A naive compiler will reload the file every time it's included. To
avoid that, put RedundantIncludeGuards around the include: header.h

 #ifndef HEADER_H_
#define HEADER_H_
// declarations
#endif

foo.c

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

read more here. Your reference claims that by doing so you can be as much as 20% faster during compilation than you would be if foo.c were only doing

 #include "header.h"

#include header guard format?

I always included the namespace or relative path in the include guard, because only the header name alone has proven to be dangerous.

For example, you have some large project with the two files somewhere in your code

/myproject/module1/misc.h
/myproject/module2/misc.h

So if you use a consistent naming schema for your include guards you might end up with having _MISC_HPP__ defined in both files (very funny to find such errors).

So I settled with

MYPROJECT_MODULE1_MISC_H_
MYPROJECT_MODULE2_MISC_H_

These names are rather long, but compared with the pain of double definitions it is worth it.

Another option, if you don't need compiler/platform independence you might look for some #pragma once stuff.

What exactly do C include guards do?

It's a preprocessor macro.

All of it is preprocessor syntax, that basically says, if this macro has not already been defined, define it and include all code between the #ifndef and #endif

What it accomplishes is preventing the inclusion of file more than once, which can lead to problems in your code.

Your question:

And why is it okay to forget the include guard in which case we can also forgot adding #define HEADER_FILE?

It's OK to forget it because it's still legal C code without it. The preprocessor processes your file before it's compiled and includes the specified code in your final program if there's no logic specifying why it shouldn't. It's simply a common practice, but it's not required.

A simple example might help illustrate how this works:

Your header file, header_file.h we'll say, contains this:

#ifndef HEADER_FILE
#define HEADER_FILE

int two(void){
return 2;
}

#endif

In another file (foo.c), you might have:

#include "header_file.h"

void foo() {
int value = two();
printf("foo value=%d\n", value);
}

What this will translate to once it's "preprocessed" and ready for compilation is this:

int two(void){
return 2;
}

void foo() {
int value = two();
printf("foo value=%d\n", value);
}

All the include guard is accomplishing here is determining whether or not the header contents between the #ifndef ... and #endif should be pasted in place of the original #include.

However, since that function is not declared extern or static, and is actually implemented in a header file, you'd have a problem if you tried to use it in another source file, since the function definition would not be included.



Related Topics



Leave a reply



Submit