The C preprocessor, also used with C++ and optionally with Fortran, is a stream editor specially designed to modify source code. It recognizes language tokens, such as variable names, numeric constants, strings, etc.
Preprocessing was added to Fortran by developers who found the features useful in C. The Fortran preprocessor is based on the C preprocessor and is actually the same program in some cases.
Preprocessor actions are designated by directives, which are indicated by a '#' as the first character on the line. The preprocessor is line-oriented, unlike the C and C++ compilers, which are completely free-format.
The C preprocessor is used to define named constants. The names are simply replaced by their value with a simple text substitution.
The #define
directive is followed by an identifier
that must follow the same naming conventions as a C variable,
i.e. it must begin with a letter or underscore, and subsequent
characters can be letters, underscores, or digits.
#define
typically use
all capital letters, so that they can be easily distinguished
from variables where they are used in statements.
#define PI 3.14159265358979323846 #define RADIUS_PROMPT "Please enter the radius: "
Constants are actually the simplest case of what
#define
can be used for. It can also be used to
define macros, which are discussed
in the section called “C Preprocessor Macros”.
The #include
directive inserts the contents of
another source file into the stream at the point where the
#include
appears.
The files included are known as header files. The use a file name extension of ".h" for C and ".hpp" for C++. They contain things like constant definitions, type definitions, and prototypes, which may be used by many other source files. Factoring out commonly used code in this way eliminates redundancy and greatly reduces the maintenance cost of the source code.
Suppose we have the following C program:
#include "constants.h" int main() { printf("PI = %f and Avogadro's constant is %f.\n", PI, AVOGADRO); return 0; }
The file "constants.h" contains the following:
#define PI 3.141592653589 #define AVOGADRO 6.02e23
The output of the C preprocessor, which is passed on to the compiler, will then be the following:
int main() { printf("PI = %f and Avogadro's constant is %f.\n", 3.141592653589, 6.02e23); return 0; }
Header files provided by the system or installed globally with
libraries have their names enclosed in angle brackets. The
preprocessor looks for these headers in
/usr/include
by default.
For example, to include /usr/include/stdio.h
and /usr/include/sys/types.h
in your program,
simply use the following:
#include <stdio.h> #include <sys/types.h>
cc myprog.c -o myprog
The -I
flag indicates additional directories
to check for headers. The path indicated in #include
is relative to the prefix specified with -I
.
For example,
if you are using vector functions from the GNU Scientific Library
(GSL) and the GSL headers are installed in
/usr/local/include/gsl
, then you could
do the following:
#include <gsl/gsl_vector.h>
cc -I/usr/local/include myprog.c -o myprog
Alternatively, you could use the following:
#include <gsl_vector.h>
cc -I/usr/local/include/gsl myprog.c -o myprog
Header files that are part of the project and reside in the same directory as the code being compiled are enclosed in double quotes.
#include "constants.h"
C++ compilers use the exact same directives and compiler flags.
The gfortran compiler will use them as well,
as long as it is told to use the preprocessor by specifying
-cpp
or by using an appropriate filename extension
such as ".fpp" or ".F90" instead of ".f90".
How does the C preprocessor differ from other stream editors, such as sed?
What languages use the preprocessor?
Show a preprocessor directive that defines a constant named HOME_PLANET with the value "Earth".
What is the output of the preprocessor for the following code:
// planets.c #include "planets.h" int main() { printf("My home planet is %s.\n", HOME_PLANET); return 0; } // planets.h #define HOME_PLANET "Earth"
What kind of code should and should not be placed in header files?
Show a command for compiling the following program,
prog1.c
, to prog1
, if
stdio.h
is a standard header file in
/usr/include
and
xtend/math.h
represents
/usr/local/include/xtend/math.h
.
#include <stdio.h> #include <xtend/math.h> int main() { return 0; }