411 REFERENCE · Wikibooks
A Little C Primer/C Preprocessor Directives
Reference material by Wikibooks contributors. This retains its source identity and is not 411 news reporting.
We've already seen the "#include" and "#define" preprocessor directives.
The C preprocessor supports several other directives as well. All such
directives start with a "#" to allow them to be distinguished from C language
commands.
As explained in the first chapter, the "#include" directive allows the
contents of other files to be included in C source code:
#include <stdio.h>
Notice that the standard header file "stdio.h" is specified in angle
brackets. This tells the C preprocessor that the file can be found in the
standard directories designated by the C compiler for header files. To
include a file from a nonstandard directory, use double quotes:
#include "\home\mydefs.h"
Include files can be nested. They can call other include files.
Also as explained in the first chapter, the "#define" directive can be used
to specify symbols to be substituted for specific strings of text:
#define PI 3.141592654
...
a = PI * b;
In this case, the preprocessor does a simple text substitution on PI
throughout the source listing. The C compiler proper not only does not know
what PI is, it never even sees it.
The "#define" directive can be used to create function-like macros that allow
parameter substitution. For example:
#define ABS(value) ( (value) >=0 ? (value) : -(value) )
This macro could then be used in an expression as follows:
printf( "Absolute value of x = %d\n", ABS(x) );
Beware that such function-like macros don't behave exactly like true
functions. For example, suppose "x++" is as an argument for the macro above:
val = ABS(x++);
This would result in "x" being incremented twice because "x++" is
substituted in the expression twice:
val = ( (x++) >=0 ? (x++) : -(x++) )
Along with the "#define" directive, there is also an "#undef" directive that
undefines a constant that has been previously defined:
#undef PI
Another feature supported by the C preprocessor is conditional compilation,
using the following directives:
#if
#else
#elif
#endif
These directives can test the values of defined constants to define which
blocks of code are passed on to the C compiler proper:
#if WIN == 1
#include "WIN.H"
#elif MAC == 1
#include "MAC.H"
#else
#include "LINUX.H"
#endif
These directives can be nested if needed. The "#if" and "#elif" can also
test to see if a constant has been defined at all, using the "defined"
operator:
#if defined( DEBUG )
printf( "Debug mode!\n");
#endif—or test to see if a constant has not been defined:
#if !defined( DEBUG )
printf( "Not debug mode!\n");
#endif
Finally, there is a "#pragma" directive, which by definition is a catch-all
used to implement machine-unique commands that are not part of the C
language. Pragmas vary from compiler to compiler, since they are by
definition nonstandard.