Noeud:The Preprocessor, Noeud « Next »:, Noeud « Previous »:Basic Compilation Options, Noeud « Up »:GCC Commands



The Preprocessor

Before any stages of compilation occur, you must first create a source file. This will be some high-level language ASCII text file containing your code. The purpose of the preprocessor is to perform textual substitutions within the code where needed. Textual substitution can come in a number of different forms: header file inclusion, macro substitution and comment substitution.

Produce preprocessed output by passing the -E flag to gcc. This will write to stdout the contents of all source files after being preprocessed, stripping out comments. To produce preprocessed output with comments (such that the preprocessor does not strip them out), include the -C flag along with the -E option.

Although you can pass the -E flag to gcc, you can also invoke the preprocessor, cpp, directly. Try cpp --help for a full listing of options available for cpp.

There are a number of reasons why you may want to view the output of the preprocessor. Firstly, it can reveal if any lines of code have been stripped out by the preprocessor due to bad commenting. Viewing preprocessed output can also be useful when viewing the results of expanding macros.

The preprocessed file includes a number of line numbers for any #include statements in the source file. For example, the output of the source file below:

     /* main.c */
     #include <stdio.h>
     int main()
     {
             return(0);
     }
     

results in the following output for the preprocessed file when it's been filtered (using a utility like grep1 for example) to search for all lines beginning with a '#':

     $ gcc -E main.c > main.i
     $ grep '^#' main.i
     # 1 "simple.c"
     # 1 "/usr/include/stdio.h" 1 3
     # 1 "/usr/include/features.h" 1 3
     # 138 "/usr/include/features.h" 3
     # 196 "/usr/include/features.h" 3
     # 1 "/usr/include/sys/cdefs.h" 1 3
     # 71 "/usr/include/sys/cdefs.h" 3
     # 103 "/usr/include/sys/cdefs.h" 3
     # 250 "/usr/include/features.h" 2 3
     # 1 "/usr/include/gnu/stubs.h" 1 3
     # 278 "/usr/include/features.h" 2 3
     # 27 "/usr/include/stdio.h" 2 3
     # 1 "/usr/lib/gcc-lib/i486-suse-linux/2.95.2/include/stddef.h" 1 3
     # 19 "/usr/lib/gcc-lib/i486-suse-linux/2.95.2/include/stddef.h" 3
     ...
     (the rest is left out because of space limitations.)
     ...
     $
     

It is worth briefly mentioning what this means, since this convention is rather hermetic unless it has been encountered before. Such file inclusions are organised as follows:

# line_number file_name flags

where the flags are defined as follows:

1 - The start of a new file

2 - Return to a new file after including another file

3 - The text included from this inclusion is a system header file; so supress certain warnings

4 - The following text should be treated as C

Thus, in the example above, # 1 "/usr/include/stdio.h" 1 3 is saying "at line number 1 in stdio.h, note the start of the file and also that this is a system header file"; note that stdio.h includes features.h (look at the flags and compare them with the descriptions above), which itself includes cdefs.h, which returns to features.h and then includes stubs.h, and finally returns to stdio.h.

Once the file has been preprocessed, and header files have been included and any macros have been expanded, it is passed on to the compiler.


Notes de bas de page

  1. grep is used for searching patterns in a line