14.1. Inserting the Contents of Header FilesAn #include directive instructs the preprocessor to insert the contents of a specified file in the place of the directive. There are two ways to specify the file to be inserted: #include <filename> #include "filename" Use the first form, with angle brackets, when you include standard library header files or additional header files provided by the implementation. An example: #include <math.h> // Prototypes of mathematical functions, // with related types and macros. Use the second form, with double quotation marks, to include source files specific to your programs. Files inserted by #include directives typically have names ending in .h, and contain function prototypes, macro definitions, and type definitions. These definitions can then be used in any program source file after the corresponding #include directive. An example: #include "myproject.h" // Function prototypes, type definitions // and macros used in my project. You may use macros in an #include directive. If you do use a macro, the macro's replacement must result in a correct #include directive. Example 14-1 demonstrates such #include directives. Example 14-1. Macros in #include directives#ifdef _DEBUG_ #define MY_HEADER "myProject_dbg.h" #else #define MY_HEADER "myProject.h" #endif #include MY_HEADER If the macro _DEBUG_ is defined when this segment is preprocessed, then the preprocessor inserts the contents of myProject_dbg.h. If not, it inserts myProject.h. The #ifdef, #else, and #endif directives are described in detail in the section "Conditional Compiling," later in this chapter. 14.1.1. How the Preprocessor Finds Header FilesIt is up to the given C implementation to define where the preprocessor searches for files specified in #include directives. Whether filenames are case-sensitive is also implementation-dependent. For files specified between angle brackets (<filename>), the preprocessor usually searches in certain system directories, such as /usr/local/include and /usr/include on Unix systems, for example. For files specified in quotation marks ("filename"), the preprocessor usually looks in the current directory first, which is typically the directory containing the program's other source files. If such a file is not found in the current directory, the preprocessor searches the system include directories as well. A filename may contain a directory path. If so, the preprocessor looks for the file only in the specified directory. You can always specify your own search path for #include directives, either by using an appropriate command-line option in running the compiler, or by adding search paths to the contents of an environment variable, often named INCLUDE. Consult your compiler's documentation. 14.1.2. Nested #include Directives#include directives can be nested ; that is, a source file inserted by an #include directive may in turn contain #include directives. The preprocessor permits at least 15 levels of nested includes. Because header files sometimes include one another, it can easily happen that the same file is included more than once. For example, suppose the file myProject.h contains the line: #include <stdio.h> Then a source file that contains the following #include directives would include the file stdio.h twice, once directly and once indirectly: #include <stdio.h> #include "myProject.h" However, you can easily guard the contents of a header file against multiple inclusions using the directives for conditional compiling (explained in "Conditional Compiling," later in this chapter). Example 14-2 demonstrates this usage. Example 14-2. Preventing multiple inclusions#ifndef INCFILE_H_ #define INCFILE_H_ /* ... The actual contents of the header file incfile.h are here ... */ #endif /* INCFILE_H_ */ At the first occurrence of a directive to include the file incfile.h, the macro INCFILE_H_ is not yet defined. The preprocessor therefore inserts the contents of the block between #ifndef and #endifincluding the definition of the macro INCFILE_H_. On subsequent insertions of incfile.h, the #ifndef condition is false, and the preprocessor discards the block up to #endif. |