0

Per this question, it seems there is some flexibility to how you can write that--

#ifndef _HEADER_H

or:

#ifndef __HEADER___H__

etc. It's not set in stone.

But I don't understand why we're using underscores at all in the first place. Why can't I just write:

#ifndef header.h

What's wrong with that? Why are we placing underscores everywhere and capitalizing everything? What does the preprocessor do with underscores?

Community
  • 1
  • 1
temporary_user_name
  • 35,956
  • 47
  • 141
  • 220

2 Answers2

6

header.h is not a valid identifier. You cannot have a period in a macro name.

That said, the name you pick for your include guard macros is completely arbitrary. After all, it's just another variable. It is purely convention (and reasonable in order to avoid clashes) to name them after the file.

I encourage you to phrase the header structure out aloud to see what the preprocessor does.

#ifndef MY_HEADER_H    /* If the macro MY_HEADER_H is not defined (yet)... */
#define MY_HEADER_H    /* ... then define it now ... */

...                    /* ... and deal with all this stuff ... */

#endif                 /* ... otherwise, skip all over it and go here. */

You see that this mechanism works equally well if you substitute MY_HEADER_H with I_REALLY_LIKE_BANANAS or whatever. The only requirement is that it be a valid macro identifier and not clash with the name of any other include guard.

In the above example, the macro is defined empty. That's fine, but it is not the only option. The second line could equally well read

#define MY_HEADER_H 1

which would then define the macro to 1. Some people do this but it doesn't really add anything and the value 1 is rather arbitrary. I generally don't do this. The only advantage is that if you define it to 1, you can also use #if in addition to #ifdef.

A final word of caution: Identifiers that start with an underscore or contain two or more consecutive underscore characters are reserved for the implementation and should not be used in user-code. Hence, _MY_HEADER_H and __MY_HEADER__H__ are both unfortunate choices.

The logic by which the preprocessor finds the correct header file if you say

#include <myheader.h>

is completely unrelated. Here, myheader.h names a file and the preprocessor will search for it in a number of directories (that usually can e configured via the -I command line option). Only after it has found and opened the file it will go ahead parsing it and thereby, it will eventually find the include guards that will cause it to essentially skip over the file if it has already parsed it before (and the include guard macro is therefore already defined so the first check evaluates to false).

5gon12eder
  • 24,280
  • 5
  • 45
  • 92
  • Emphasis for the second part of this: there is *no connection* between the filename and the macro except in the reader's mind. – Alex Celeste Jan 13 '15 at 19:48
  • Okay, but then where does the macro get its value in the first place, if the system draws no association? `#ifndef HEADER_H`....how would the system know if it was defined or not? Where is that macro's definition? – temporary_user_name Jan 13 '15 at 19:51
  • On the second line. You can define it to a value if you like, but an empty definition is also fine. – 5gon12eder Jan 13 '15 at 19:52
  • So...(I'm new to C)...is that to say you would not use `#include "header.h"` *and* use `#ifndef`/`#define` to duplicate that header? I'm trying to figure out how the two should be used relative to one another, which scenario each is specifically for. – temporary_user_name Jan 13 '15 at 19:54
  • You need to include a header wherever you need the definitions inside. The so-called inclusion-guards are used to prevent multiple includes of the same declarations, which can happen if header A includes header B, and both include header C. A non-standard but normally even cross-platform way to accomplish this is the "#pragma once" directive, you can safely use that. – deets Jan 13 '15 at 19:57
  • 2
    @Aerovistae It's not used to duplicate the header, it's used to prevent duplicate inclusion of the header file. http://en.wikipedia.org/wiki/Include_guard has a fair explanation of what goes on, and why these include guards are needed. – nos Jan 13 '15 at 20:08
  • Yep, just found that on my own and read through it, understand perfectly now. Thank you. – temporary_user_name Jan 13 '15 at 20:11
1

Because #ifdef or #ifndef requires a preprocessor symbol after it, and these symbols cannot contain dots.

In the C11 (latest draft) spec n1570 (§6.10.1):

Preprocessing directives of the forms

# ifdef identifier new-line group opt

# ifndef identifier new-line group opt

check whether the identifier is or is not currently defined as a macro name.

and identifiers cannot contain dots (§6.4.2.1)

BTW, include guards are not required to have #ifdef symbols related to the file name. You can have a header file foo.h guarded with a #ifndef JESUISCHARLIEHEBDO or by
#ifndef I_LOVE_PINK_ROSES_BUT_NOT_YELLOW_ONES preprocessor directive if you want so. But by human convention, the names are often related. Notice that identifiers starting with an underscore are implementation defined, so you should rather avoid #ifndef _FOO_INCLUDED but prefer #ifndef FOO_INCLUDED

Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547