The #if directive, together with the #elif, #else, and #endif directives, controls compilation of portions of a source file. If the expression you write (after the #if) has a nonzero value, the statements immediately following the #if directive are retained in the translation unit.
preprocessing-file :
group opt
group :
group-part
group group-part
group-part :
pp-tokens opt new-line
if-section
control-line
if-section :
if-group elif-groups opt else-group opt endif-line
if-group :
#if restricted-constant-expression new-line group opt
#ifdef identifier new-line group opt
#ifndef identifier new-line group opt
elif-groups :
elif-group
elif-groups elif-group
elif-group :
#elif restricted-constant-expression new-line group opt
else-group :
#else new-line group opt
endif-line :
#endif new-line
control-line :
#include "path-spec" new-line /* Programmer-supplied header files */
#include <path-spec> new-line /* Standard C header files */
#define identifier replacement-list new-line /* Macro with arguments */
#define identifier (identifier-listopt new-line) replacement-list
#undef identifier new-line
#line digit-sequence new-line
#line digit-sequence "filename" opt new-line
#line digit-sequence preprocessing-tokens new-line
#error preprocessor-tokens opt new-line
#pragma pragma-directive opt new-line
# new-line
replacement-list :
pp-tokens opt
pp-tokens :
preprocessing-token
pp-tokens preprocessing-token
preprocessing-token :
header-name
identifier
pp-number
character-constant
string-literal
operator
punctuator
each nonwhite-space character that cannot be one of the above
new-line : the newline character
Each #if directive in a source file must be matched by a closing #endif directive. Any number of #elif directives can appear between the #if and #endif directives, but at most one #else directive is allowed. The #else directive, if present, must be the last directive before #endif.
The #if, #elif, #else, and #endif directives can nest in the text portions of other #if directives. Each nested #else, #elif, or #endif directive belongs to the closest unmatched #if directive.
The preprocessor selects a single group by evaluating the restricted constant expression following each #if or #elif directive until it finds a true (nonzero) restricted constant expression. It selects all text (including other preprocessor directives beginning with #) up to its associated #elif, #else, or #endif.
The constant expressions used with the #if directives are called restricted-constant-expressions since some restrictions apply here that do not apply to all constant expressions. The preprocessor processes the selected group and passes it to the compiler. If group contains preprocessor directives, the preprocessor carries out those directives. Any text blocks not selected by the preprocessor are not compiled.
If all occurrences of restricted-constant-expression are false, or if no #elif directives appear, the preprocessor selects the text block after the #else clause. If the #else clause is omitted, and all instances of restricted-constant-expression in the #if block are false, no text block is selected.
The Restricted Constant Expression
The restricted-constant-expression is an integer constant expression with these additional restrictions:
All expressions must have integral type and can only include integer constants and character constants.
The expression cannot use sizeof or a type cast operator, nor can assignment operators and the sequential evaluation operator (,) be used in the constant expression.
The translation represents type int the same as type long and unsigned int the same as unsigned long.
The compiler can translate character constants to a set of code values different from the set for the target environment. To determine the properties of the target environment, check values of macros from LIMITS.H in an application built for the target environment. The target environment may not be able to represent all ranges of integers.
The expression must not perform any environmental inquiries and must remain insulated from implementation details on the target computer.
The restricted-constant-expression can contain the preprocessor operator defined as shown:
defined(identifier) defined identifier /* Alternative equivalent form */
This constant expression is considered true (nonzero) if the identifier is currently defined as a macro; otherwise, the condition is false (0). An identifier defined as empty text is considered defined. The defined directive can be used in a #if and a #elif, but nowhere else.
In the following example, the #if and #endif directives control compilation of one of three function calls.
#if defined(CREDIT)
credit();
#elif defined(DEBIT)
debit();
#else
printerror();
#endif
The function call to credit is compiled if the macro CREDIT is defined. If the identifier DEBIT is defined, the function call to debit is compiled. If neither identifier is defined, the call to printerror is compiled. Note that CREDIT and credit are distinct identifiers in C because their cases are different.
The following conditional compilation statements assume a constant named DLEVEL has already been defined. If an identifier used with #if has not been defined, the identifier evalutes to 0.
#if DLEVEL > 5 /* First example */
#define SIGNAL 1
#if STACKUSE == 1
#define STACK 200
#else
#define STACK 100
#endif
#else
#define SIGNAL 0
#if STACKUSE == 1
#define STACK 100
#else
#define STACK 50
#endif
#endif
#if DLEVEL == 0 /* Second example */
#define STACK 0
#elif DLEVEL == 1
#define STACK 100
#elif DLEVEL > 5
display( debugptr );
#else
#define STACK 200
#endif
The #if block in the first example shows two sets of nested #if, #else, and #endif directives. The first set of directives is processed only if DLEVEL > 5 is true. Otherwise, the statements after the #else are processed.
The #elif and #else directives in the second example are used to make one of four choices, based on the value of DLEVEL. The constant STACK is set to 0, 100, or 200, depending on the definition of DLEVEL. If DLEVEL is greater than 5, then the statement
#elif DLEVEL > 5
display(debugptr);
is compiled and STACK is not defined.
Microsoft Specific
The identifiercan be passed from the command line using the /D option. Up to 30 macros can be specified with /D.This is useful for checking if a definition exists since a definition can be passed from the command line. For example,
#if !defined test /* These three statements go in your source code */
#define final
#endif
CL /Dtest /* This is the command for compilation */
In this example, a macro named final is defined if test has not been defined. You can enter either test or final from the command line at compilation time. The example above shows test being entered from the command line. Alternatively, you can use PWB. From the PWB Options menu, choose Language Options. Then select Additional Global Options or Additional Debug Options and type the constants for your program.
Conditional compilation expressions are treated as signed long values. For example, this expression is true:
#if 0xFFFFFFFFL > 1UL
These expressions are evaluated using the same rules as expressions in C.¨