14.3. Conditional Compiling
The conditional compiling directives instruct the preprocessor to retain or omit parts of the source code depending on specified conditions. You can use conditional compiling to adapt a program to different target systems, for example, without having to manage a variety of source files.
A conditional section begins with one of the directives #if, #ifdef, or #ifndef, and ends with the directive #endif. Any number of #elif directives, and at most one #else directive, may occur within the conditional section. A conditional section that begins with #if has the following form:
#if expression1 [ group1 ] [#elif expression2 [ group2 ]] ... [#elif expression(n) [ group(n) ]] [#else [ group(n+1) ]] #endif
The preprocessor evaluates the conditional expressions in sequence until it finds one whose value is nonzero, or "true." The preprocessor retains the text in the corresponding group for further processing. If none of the expressions is true, and the conditional section contains an #else directive, then the text in the #else directive's group is retained.
The token groups group1, group2, and so on consist of any C source code, and may include more preprocessing directives, including nested conditional compiling directives. Groups that the preprocessor does not retain for further processing are removed from the program at the end of the preprocessor phase.
14.3.1. The #if and #elif Directives
The expression that forms the condition of an #if or #elif directive must be an integer constant preprocessor expression. This is different from an ordinary integer constant expression (see "Constant Expressions" in Chapter 5) in these respects:
14.3.2. The defined Operator
The unary operator defined can occur in the condition of an #if or #elif directive. Its form is one of the following:
defined identifier defined (identifier)
These preprocessor expressions yield the value 1 if the specified identifier is a macro namethat is, if it has been defined in a #define directive and its definition hasn't been canceled by an #undef directive. For any other identifier, the defined operator yields the value 0.
The advantage of the defined operation over the #ifdef and #ifndef directives is that you can use its value in a larger preprocessor expression. An example:
#if defined( _ _unix_ _ ) && defined( _ _GNUC_ _ ) /* ... */ #endif
Most compilers provide predefined macros, like those used in this example, to identify the target system and the compiler. Thus on a Unix system, the macro _ _unix_ _ is usually defined, and the macro _ _GNUC_ _ is defined if the compiler being used is GCC. Similarly, the Microsoft Visual C compiler on Windows automatically defines the macros _WIN32 and _MSC_VER.
14.3.3. The #ifdef and #ifndef Directives
You can also test whether a given macro is defined using the #ifdef and #ifndef directives. Their syntax is:
#ifdef identifier #ifndef identifier
These are equivalent to the following #if directives:
#if defined identifier #if !defined identifier
The conditional code following the #ifndef identifier is retained if identifier is not a macro name. Examples 14-1 and 14-2 illustrate possible uses of these directives.