Why does each .h file starts with #ifndef #define #endif? We can certainly compile the program without those directives.
views:
299answers:
5It'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.
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.
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.
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 onceinstead of
ifndef
's.
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 #include
d 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.