Header Files
Header files are files with the extension .h that contain C function declarations and macro definitions to be shared between several source files. There are two types of header files: those written by the programmer and those provided by the compiler.
To use a header file in a program, you need to include it using the C preprocessor directive #include. We have already seen the stdio.h header file, which is provided by the compiler.
Including a header file means copying its content, but we do not directly copy the content of the header file into the source file because it can easily lead to errors, especially when the program consists of multiple source files.
A common practice in C or C++ programs is to place all constants, macros, system-wide global variables, and function prototypes in header files, and include these header files whenever needed.
Syntax for Including Header Files
The preprocessor directive #include can be used to include both user and system header files. It has two forms:
#include <file>
This form is used for including system header files. It searches for the file named file
in a standard list of system directories. You can add directories to this list by using the -I
option when compiling the source code.
#include "file"
This form is used for including user header files. It searches for the file named file
in the directory containing the current file. You can also add directories to this list by using the -I
option when compiling the source code.
Operation of Including Header Files
The #include directive instructs the C preprocessor to browse the specified file as input. The output of the preprocessor includes the generated output, the output produced by the included file, and the text output following the #include directive. For example, if you have a header file header.h
as follows:
char *test (void);
And a main program program.c
that uses the header file, as follows:
int x;
#include "header.h"
int main (void)
{
puts (test ());
}
The compiler will see the following code:
int x;
char *test (void);
int main (void)
{
puts (test ());
}
Including a Header File Only Once
If a header file is included twice, the compiler will process its content twice, which will result in an error. To prevent this, the standard practice is to wrap the entire content of the file in conditional compilation statements, as follows:
#ifndef HEADER_FILE
#define HEADER_FILE
the entire header file content
#endif
This structure is commonly referred to as a wrapper #ifndef. When the header file is included again, the condition will be false because HEADER_FILE
is already defined. The preprocessor will skip the entire content of the file, and the compiler will ignore it.
Conditional Inclusion
Sometimes you need to include one of several different header files in your program. For example, you may need to specify configuration parameters for different operating systems. You can achieve this using a series of conditions, as follows:
#if SYSTEM_1
# include "system_1.h"
#elif SYSTEM_2
# include "system_2.h"
#elif SYSTEM_3
...
#endif
However, this approach is not practical when there are many header files. The preprocessor uses macros to define the names of the header files. This is known as conditional inclusion. Instead of using the header file name directly as the argument for #include, you can use a macro name:
#define SYSTEM_H "system_1.h"
...
#include SYSTEM_H
SYSTEM_H
will expand, and the preprocessor will look for system_1.h
as if #include was originally written that way. SYSTEM_H
can be defined by your Makefile using the -D
option.