views:

299

answers:

5

Why does each .h file starts with #ifndef #define #endif? We can certainly compile the program without those directives.

+12  A: 

It's a so-called "include guard". The purpose is to prevent the file from having to be parsed multiple times if it is included multiple times.

janneb
And to prevent multiple definitions of the same class.
Autopulated
Was there ever an #import directive, or is that just my imagination?
Tom R
@Autopulated: That's what he means by getting parsed multiple times. There are more things than class redefinitions to worry about; all are encapsulated by "multiple parsing".
GMan
@janneb @GMan: I know all of these things but I don't know what it can be exactly. I know about redefinitions of class, variables etc. but it is uncomfortable but not dangerous. Can you give me some examples of dangerous behavior please?
Gaim
I'm not sure I understand your terminology. Redefinitions are compile errors, I don't think it gets any "worse" than that.
GMan
@Tom: No. Import was invented in subsequent languages (those that came after C). It was realized during the design of these languages, that not all programmers were smart enough to use #include correctly so an automated method was introduced for those languages (import). </Sarcasm> Did I forget to turn that on. Whoops.
Martin York
@GMan I know about compile errors but if I ignore it are there any things which can devastate expected program behavior? Because no all of header files have to contain definition of class variable etc. I can use there guards in these files to prevent error. But there are also other instruction for preprocesor ( for example ) and I am interest if exist some things which don't cause compile error but can cause unexpected program behavior. ( I hope that it is understandable )
Gaim
I think I understand. I can't think of anything, probably because guards are to protect from syntax errors, not program errors. That is to say, taking out the guards can only give you compile errors, not change program behavior.
GMan
@GMan Thanks a lot, that is what I want to read
Gaim
@Tom: you might recall that from Visual C++, its a vendor-specific extension for COM type libraries. Or from Objective-C/C++.
Georg Fritzsche
+2  A: 

It is called an include guard. You can write without them until you start writing large programs and find out that you need to include the same .h file more than once, directly or indirectly, from a .c file. Then without include guards you would get multiple definition errors, but with them, the header file contents are parsed only once and skipped all the subsequent times, avoiding those errors. It`s a good practice to always use them.

Laurynas Biveinis
+3  A: 

It prevents multiple inclusions of a single file. The same can be done using

#pragma once

directive, but those #ifndefs are standard thus supported by every compiler.

el.pescado
#pragma once. Is a compiler specific extension.
Martin York
...but a widely supported one, to be fair
Terry Mahaffey
A: 

If a header file contains definition like

int i;
than, being included several times without a guard, will produce a compilation error.
ifndef checks that some preprocessor variable is not defined (and it is not, for a first time), then defines it explicitly to avoid being captured again. In MSVC you can also use
#pragma once
instead of ifndef's.

alemjerus
A: 

If I understand correctly, you want to know if, in the absence of include guards, can including a header file multiple times cause an error or dangerous behavior. This is after excluding multiple definitions, etc.

Imagine a malicious programmer, whose header file doesn't have the include guards. His header file defines one macro, SZ, which is a size that you use for your statically allocated arrays. The programmer could write his header file like this:

#ifndef SZ
#define SZ 1024
#else
#if SZ == 1024
#undef SZ
#define SZ 128
#else
#error "You can include me no more than two times!"
#endif
#endif

Now, if you include the header file once, you get SZ equal to 1024. If you include it twice, SZ becomes 128. Of course, most real-world programmers are not malicious, and no one really writes code like above.

Note that the C standard allows assert.h to be #included more than once with different behavior depending upon whether NDEBUG is defined at the time of inclusion of assert.h. So, assert.h can't have include guards. That is a feature, not a bug, though.

Alok