Preprocessor occurs prior to the formal compilation stage. In simple terms, a C Preprocessor is just a text substitution tool and it instructs the compiler to do required pre-processing before the actual compilation. We’ll refer to the C Preprocessor as CPP.
The preprocessing stage modifies the content of the source file based on preprocessing directives in the placed files. For example, #include directive is a preprocessing directive that adds the content of a file to a cpp file. All preprocessor commands begin with a hash symbol (#). It must be the first nonblank character, and for readability, a preprocessor directive should begin in the first column. The following section lists down all the important preprocessor directives.
The following section lists down all the important preprocessor directives −
Sr.No. | Directive & Description |
---|---|
1 | #define
Substitutes a preprocessor macro. |
2 | #include
Inserts a particular header from another file. |
3 | #undef
Undefines a preprocessor macro. |
4 | #ifdef
Returns true if this macro is defined. |
5 | #ifndef
Returns true if this macro is not defined. |
6 | #if
Tests if a compile time condition is true. |
7 | #else
The alternative for #if. |
8 | #elif
#else and #if in one statement. |
9 | #endif
Ends preprocessor conditional. |
10 | #error
Prints error message on stderr. |
11 | #pragma
Issues special commands to the compiler, using a standardized method. |
This method of modifying the source file prior to compilation provides great flexibility to adapt to different computer and operating system environments.
The executable code required by one environment may differ from that required by another due to differences in available hardware architecture and operating systems.
In many cases (especially in embedded development), code for different environments can be placed in the same file and modified in the preprocessing stage to adapt to the environment.
The preprocessing stage mainly involves the following processes:
Macro definition directives, such as #define, M a;
For these pseudo-instructions, the precompiler replaces all instances of M in the program with a. It is important to note that if M is a character constant, it will not be replaced (because it is already a constant and its value is determined). Conversely, #undef cancels the definition of a macro, so that it will not be replaced in subsequent occurrences.
Conditional compilation directives, such as #ifdef, #ifndef, #else, #elif, #endif, etc.
These pseudo-instructions enable programmers to determine which code the compilation program processes by defining different macros. In other words, the precompiler program filters out unnecessary code based on the relevant files.
Header file inclusion directives, such as #include, etc.
In header files, many macros (most commonly character constants) are defined using #define, and external symbol declarations are also included.
The main purpose of using header files is to allow certain definitions to be used by multiple different C source programs. When these C source programs need to use these definitions, they only need to add an #include statement, and do not need to repeat these definitions in the current file.
The precompiler program will add all definitions in the header file to the output file it produces for processing by the compilation program.
In the Linux operating system, the header files included in C source programs can be system-provided, and these header files are generally placed in the /usr/include/ directory. To use them in a program, #include should use angle brackets <>.
In addition, developers can also define their own header files, which are generally placed in the same directory as the C source program. In this case, “” should be used in #include.
Special symbols: The precompiler program can recognize some special symbols.
For example, the LINE identifier that appears in the source program is interpreted as the current line number (in decimal), FILE is interpreted as the name of the C source program currently being compiled, and FUNCTION is interpreted as the name of the function in the C source program currently being compiled. The precompiler program replaces these strings that appear in the source program with appropriate values, which are often used together to debug the program.
Finally, it is important to emphasize that the preprocessing stage is not part of the precompilation process, which is a common mistake made by beginners.
The precompiler program basically performs “replacement” of the source program. After this replacement, an output file without macro definitions, conditional compilation directives, and special symbols is generated. The meaning of this file is the same as that of the source file that has not been preprocessed, but its content is different. In the next step, this output file will be translated into machine instructions as the output of the compilation program.
Predefined Macros
ANSI C defines a number of macros. Although each one is available for use in programming, the predefined macros should not be directly modified.
Sr.No. | Macro & Description |
---|---|
1 | __DATE__
The current date as a character literal in “MMM DD YYYY” format. |
2 | __TIME__
The current time as a character literal in “HH:MM:SS” format. |
3 | __FILE__
This contains the current filename as a string literal. |
4 | __LINE__
This contains the current line number as a decimal constant. |
5 | __STDC__
Defined as 1 when the compiler complies with the ANSI standard. |
The preprocessor program essentially performs a “substitution” of the source code. After this substitution, an output file is generated that has no macro definitions, no conditional compilation directives, and no special symbols. This file has the same meaning as the source file without preprocessing, but the contents are different. The next step is for this output file to be translated into machine instructions by the compiler program.
For More information about Preporcessor, please check The C Preprocessor