Is it necessary to #include
some file, if inside a header (*.h), types defined in this file are used?
For instance, if I use GLib and wish to use the
NASA's Goddard Space Flight Center (GSFC) rules for headers in C state that it must be possible to include a header in a source file as the only header, and that code using the facilities provided by that header will then compile.
This means that the header must be self-contained, idempotent and minimal:
The benefit of this rule is that if someone needs to use the header, they do not have to struggle to work out which other headers must also be included — they know that the header provides everything necessary.
The possible downside is that some headers might be included many times; that is why the multiple inclusion header guards are crucial (and why compilers try to avoid reincluding headers whenever possible).
This rule means that if the header uses a type — such as 'FILE *
' or 'size_t
' - then it must ensure that the appropriate other header (<stdio.h>
or <stddef.h>
for example) should be included. A corollary, often forgotten, is that the header should not include any other header that is not needed by the user of the package in order to use the package. The header should be minimal, in other words.
Further, the GSFC rules provide a simple technique to ensure that this is what happens:
Hence, suppose we have a Magic Sort.
#ifndef MAGICSORT_H_INCLUDED
#define MAGICSORT_H_INCLUDED
#include <stddef.h>
typedef int (*Comparator)(const void *, const void *);
extern void magicsort(void *array, size_t number, size_t size, Comparator cmp);
#endif /* MAGICSORT_H_INCLUDED */
#include <magicsort.h>
void magicsort(void *array, size_t number, size_t size, Comparator cmp)
{
...body of sort...
}
Note that the header must include some standard header that defines size_t
; the smallest standard header that does so is <stddef.h>
, though several others also do so (<stdio.h>
, <stdlib.h>
, <string.h>
, possibly a few others).
Also, as mentioned before, if the implementation file needs some other headers, so be it, and it is entirely normal for some extra headers to be necessary. But the implementation file ('magicsort.c') should include them itself, and not rely on its header to include them. The header should only include what users of the software need; not what the implementers need.
If your code uses a configuration header (GNU Autoconf and the generated 'config.h', for example), you may need to use this in 'magicsort.c':
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "magicsort.h"
...
This is the only time I know of that the module's private header is not the very first header in the implementation file. However, the conditional inclusion of 'config.h' should probably be in 'magicsort.h' itself.
The URL linked above is no longer functional (404). You can find the C++ standard (582-2003-004) at EverySpec.com; the C standard (582-2000-005) seems to be missing in action.
The guidelines from the C standard were:
§2.1 UNITS
(1) Code shall be structured as units, or as stand-alone header files.
(2) A unit shall consist of a single header file (.h) and one or more body (.c) files. Collectively the header and body files are referred to as the source files.
(3) A unit header file shall contain all pertinent information required by a client unit. A unit’s client needs to access only the header file in order to use the unit.
(4) The unit header file shall contain #include statements for all other headers required by the unit header. This lets clients use a unit by including a single header file.
(5) The unit body file shall contain an #include statement for the unit header, before all other #include statements. This lets the compiler verify that all required #include statements are in the header file.
(6) A body file shall contain only functions associated with one unit. One body file may not provide implementations for functions declared in different headers.
(7) All client units that use any part of a given unit U shall include the header file for unit U; this ensures that there is only one place where the entities in unit U are defined. Client units may call only the functions defined in the unit header; they may not call functions defined in the body but not declared in the header. Client units may not access variables declared in the body but not in the header.
A component contains one or more units. For example, a math library is a component that contains multiple units such as vector, matrix, and quaternion.
Stand-alone header files do not have associated bodies; for example, a common types header does not declare functions, so it needs no body.
Some reasons for having multiple body files for a unit:
- Part of the body code is hardware or operating system dependent, but the rest is common.
- The files are too large.
- The unit is a common utility package, and some projects will only use a few of the functions. Putting each function in a separate file allows the linker to exclude the ones not used from the final image.
§2.1.1 Header include rationale
This standard requires a unit’s header to contain
#include
statements for all other headers required by the unit header. Placing#include
for the unit header first in the unit body allows the compiler to verify that the header contains all required#include
statements.An alternate design, not permitted by this standard, allows no
#include
statements in headers; all#include
s are done in the body files. Unit header files then must contain#ifdef
statements that check that the required headers are included in the proper order.One advantage of the alternate design is that the
#include
list in the body file is exactly the dependency list needed in a makefile, and this list is checked by the compiler. With the standard design, a tool must be used to generate the dependency list. However, all of the branch recommended development environments provide such a tool.A major disadvantage of the alternate design is that if a unit’s required header list changes, each file that uses that unit must be edited to update the
#include
statement list. Also, the required header list for a compiler library unit may be different on different targets.Another disadvantage of the alternate design is that compiler library header files, and other third party files, must be modified to add the required
#ifdef
statements.A different common practice is to include all system header files before any project header files, in body files. This standard does not follow this practice, because some project header files may depend on system header files, either because they use the definitions in the system header, or because they want to override a system definition. Such project header files should contain
#include
statements for the system headers; if the body includes them first, the compiler does not check this.
Information courtesy Eric S. Bullington:
The referenced NASA C coding standard can be accessed and downloaded via the Internet archive:
http://web.archive.org/web/20090412090730/http://software.gsfc.nasa.gov/assetsbytype.cfm?TypeAsset=Standard
The question also asks:
If yes, do I also have to put it (the
#include
lines) between the#ifndef
and#define
or after the#define
.
The answer shows the correct mechanism — the nested includes, etc, should be after the #define
(and the #define
should be the second non-comment line in the header) — but it doesn't explain why that's correct.
Consider what happens if you place the #include
between the #ifndef
and #define
. Suppose the other header itself includes various headers, perhaps even #include "magicsort.h"
indirectly. If the second inclusion of magicsort.h
occurs before #define MAGICSORT_H_INCLUDED
, then the header will be included a second time before the types it defines are defined. So, in C89 and C99, any typedef
type name will be erroneously redefined (C2011 allows them to be redefined to the same type), and you will get the overhead of processing the file multiple times, defeating the purpose of the header guard in the first place. This is also why the #define
is the second line and is not written just before the #endif
. The formula given is reliable:
#ifndef HEADERGUARDMACRO
#define HEADERGUARDMACRO
...original content of header — other #include lines, etc...
#endif /* HEADERGUARDMACRO */
A good practice is to only put #includes in an include file if the include file needs them. If the definitions in a given include file are only used in the .c file then include it only in the .c file.
In your case, i would include it in the include file between the #ifdef/#endif.
This will minimize dependencies so that files that don't need a given include won't have to be recompiled if the include file changes.
Just include all external headers in one common header file in your project, e.g. global.h and include it in all your c files:
It can look like this:
#ifndef GLOBAL_GUARD
#define GLOBAL_GUARD
#include <glib.h>
/*...*/
typedef int YOUR_INT_TYPE;
typedef char YOUR_CHAR_TYPE;
/*...*/
#endif
This file uses include guard to avoid multiple inclusions, illegal multiple definitions, etc.