The following question, despite being slightly compound, all relate to the single overarching concept of compiler behavior with regards to a same header file inclusion within multiple source files.
The answer here seems to suggest that include guards for standard include files are already implemented internally. The question therefore concerns non-standard include files.
Consider the following situation:
A C program has files
module1.c
,module2.c
,module1.h
,module2.h
,apputils.c
andapputils.h
.
Both
module1.c
andmodule2.c
make use of functions defined/ implemented withinapputils.c
andapputils.h
.
Aside from required headers, each
.c
file includes their respective.h
file only.
In terms of double inclusion conflict, if code sections presented below are added to specified files (apputils.c
inclusive), which cases:
Are valid?
Cause issue?
Treated the same by the compiler?
Case 1 (within ALL):
#ifndef APPUTIL_H
#define APPUTIL_H
#include "apputils.h"
#endif
Case 2 (within module1.c
and module2.c
):
#include "apputils.h"
Case 3 (within module1.h
and module2.h
):
#include "apputils.h"
Does it matter if the inclusions are <...>
or "..."
?
Finally, for reference, please specify the recommended approach for the matter.
Look at these two Stack Overflow questions:
They discuss many of the nuances. They also discuss the concepts that header files should be self-contained, idempotent, and minimal. (Header guards ensure idempotency.)
That is, each header file should have the form:
/* Optional comments */
#ifndef HEADER_H_INCLUDED
#define HEADER_H_INCLUDED
…main content of the header…
#endif /* HEADER_H_INCLUDED */
The name of the guard macro should be unique across all headers that will ever be included in the same translation unit (TU). It is usually derived from the header file name (which should also be unique to avoid confusion).
It generally isn't worth repeating the header guards in files that use the header. All else apart, it means that if the header guards in a header change for any reason, you have to edit the code that uses that header(1). Therefore, Case 1 is not a good idea.
Additionally, with Case 1, the headers should be responsible for defining the header guard macros (the #define
should not be in the source code including the header). If the source code testing the header guards sets the header guard correctly, that will prevent the contents of the file from being included.
Case 2 is correct if the modules use the facilities exposed by apputils.h
but do not expose them in their interface to the outside world. It is often the right choice.
OTOH, Case 3 is correct if apputils.h
defines a type which is used in the interface to one of the externally exposed functions declared by either module1.h
or module2.h
. It is plausible for one of the module headers to include apputils.h
and the other not to do so. It all depends on what it takes to make the headers self-contained and minimal. (Properly used, header guards ensure the headers are idempotent.)
In a comment, mindoverflow asked:
I can explain my issue more clearly now - what if
#include "apputils.h"
appears within the guards of BOTHmodule1.h
andmodule2.h
. Those guards are different, so wouldn't this cause a conflict then? Leaving aside best practice of course, like this:#ifndef MODULE1_H #define MODULE1_H #include "apputils.h" ... #endif /* MODULE1_H */
and the same in
module2.h
but with the guard label changed?
There's no problem as long as the contents of apputils.h
has header guards around it:
#ifndef APPUTILS_H
#define APPUTILS_H
...
#endif /* APPUTILS_H */
Suppose module1.h
is included before module2.h
.
module1.h
header defines MODULE1_H
apputils.h
apputils.h
header defines APPUTILS_H
module1.h
header defines the other material it needs tomodule2.h
is includedmodule2.h
defines MODULE2_H
apputils.h
APPUTILS_H
is already defined, the contents of apputils.h
is ignored on this second usemodule2.h
header defines the other material it needs toSo, the net result is that the material from each of apputils.h
, module1.h
and module2.h
is defined once, just as you wanted. If module2.h
was included before module1.h
, the effect would be similar — the operational content of each header would appear once in the translation unit, albeit with the content of module2.h
appearing before the content of module1.h
.
This is precisely why it is crucial that the headers are self-protecting (contain the header guards), and also why it is important (if you go against advice and still decide to test for header guards before including the file) that you do not write:
#ifndef MODULE1_H
#define MODULE1_H
#include "module1.h"
#endif /* MODULE1_H */
But instead use:
#ifndef MODULE1_H
#include "module1.h"
#endif /* MODULE1_H */
If you use the first notation, you prevent the content from module1.h
from being included because the header guard is already defined when the file is read. That's not what you intended and is pointless. But it depends on the header guards being in the header file. Not putting the header guards in the header file is very bad practice.
Think how horrible it would be if you had to write:
#ifndef STDC_STDIO_H
#include <stdio.h>
#define STDC_STDIO_H
#endif /* STDC_STDIO_H */
instead of just:
#include <stdio.h>
Not nice — and not necessary.
In a another comment, mindoverflow asks:
[…] It is exactly because the header guard would prevent a double inclusion that I ask this. If I had included other headers [that] I needed for each module within the guard such that the contents within the guard are different in each module, that would definitely cause issues, right?
I'm not completely sure what you're asking, but …
If you mean that the headers module1.h
and module2.h
had each included other headers, but the sets of headers were different, there would be no problem as long as each of the headers was idempotent (contained its own header guards).
Note that the C standard requires analogous behaviour with C11 §7.1.2 Standard header files ¶4:
Standard headers may be included in any order; each may be included more than once in a given scope, with no effect different from being included only once, except that the effect of including
<assert.h>
depends on the definition ofNDEBUG
(see 7.2). If used, a header shall be included outside of any external declaration or definition, and it shall first be included before the first reference to any of the functions or objects it declares, or to any of the types or macros it defines. However, if an identifier is declared or defined in more than one header, the second and subsequent associated headers may be included after the initial reference to the identifier.
The last quoted sentence applies to the type size_t
, for example, which is defined by <stddef.h>
, but also by <stdio.h>
and <string.h>
and other headers. The system must make it work.
If each of the headers you include is itself idempotent (meaning it doesn't cause trouble if it is included more than once in a TU), there won't be problems.
And in yet another comment, they ask:
[…] It would cause an error if I had included
apputil.h
guards in a different form in all 3.h
files, right?
This is a bit difficult to parse, too. If you're still thinking of applying the header guards in code that includes the header rather than the header itself, then (a) you're doing it the wrong way (don't do it!), and (b) if you used different names in the header guard sequences in different places, you would probably, but not necessarily, end up with problems.
If the headers are not self-protecting and rely on the including code to protect them from multiple inclusion, you have to ensure that all the places that include a given header protect it the same way. In general, not being 100% consistent will cause problems because the same type (structure, union or enumeration) will be defined twice, which is not allowed. However, if the header only declares functions, you may well get away with it. But the fact that you have four lines of code per file including each header instead of just the one #include
line means you are making busy-work for yourself. (I trust you don't have a team you're working with and penalizing with your bad code design decisions.)
Please, please, please abandon any thoughts of protecting headers outside the header file. The header guard inside the header file is the idiomatic and sensible way to protect headers. Anything else is error prone and creates extra work for the teams using those headers.