|
| 1 | +--- |
| 2 | +title: "#if, #elif, #else, and #endif Directives (C-C++)" |
| 3 | +ms.custom: na |
| 4 | +ms.date: 10/03/2016 |
| 5 | +ms.devlang: |
| 6 | + - C++ |
| 7 | + - C |
| 8 | +ms.prod: visual-studio-dev14 |
| 9 | +ms.reviewer: na |
| 10 | +ms.suite: na |
| 11 | +ms.technology: |
| 12 | + - devlang-cpp |
| 13 | +ms.tgt_pltfrm: na |
| 14 | +ms.topic: article |
| 15 | +H1: #if, #elif, #else, and #endif Directives (C/C++) |
| 16 | +ms.assetid: c77a175f-6ca8-47d4-8df9-7bac5943d01b |
| 17 | +caps.latest.revision: 10 |
| 18 | +manager: ghogen |
| 19 | +translation.priority.ht: |
| 20 | + - cs-cz |
| 21 | + - de-de |
| 22 | + - es-es |
| 23 | + - fr-fr |
| 24 | + - it-it |
| 25 | + - ja-jp |
| 26 | + - ko-kr |
| 27 | + - pl-pl |
| 28 | + - pt-br |
| 29 | + - ru-ru |
| 30 | + - tr-tr |
| 31 | + - zh-cn |
| 32 | + - zh-tw |
| 33 | +--- |
| 34 | +# #if, #elif, #else, and #endif Directives (C-C++) |
| 35 | +The `#if` directive, 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 line group immediately following the `#if` directive is retained in the translation unit. |
| 36 | + |
| 37 | +## Grammar |
| 38 | + *conditional* : |
| 39 | + *if-part elif-parts*opt*else-part*opt*endif-line* |
| 40 | + |
| 41 | + *if-part* : |
| 42 | + *if-line text* |
| 43 | + |
| 44 | + *if-line* : |
| 45 | + **#if** *constant-expression* |
| 46 | + |
| 47 | + **#ifdef** *identifier* |
| 48 | + |
| 49 | + **#ifndef** *identifier* |
| 50 | + |
| 51 | + *elif-parts* : |
| 52 | + *elif-line text* |
| 53 | + |
| 54 | + *elif-parts elif-line text* |
| 55 | + |
| 56 | + *elif-line* : |
| 57 | + **#elif** *constant-expression* |
| 58 | + |
| 59 | + *else-part* : |
| 60 | + *else-line text* |
| 61 | + |
| 62 | + *else-line* : |
| 63 | + `#else` |
| 64 | + |
| 65 | + *endif-line* : |
| 66 | + `#endif` |
| 67 | + |
| 68 | + 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`. |
| 69 | + |
| 70 | + 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 preceding `#if` directive. |
| 71 | + |
| 72 | + All conditional-compilation directives, such as `#if` and **#ifdef**, must be matched with closing `#endif` directives prior to the end of file; otherwise, an error message is generated. When conditional-compilation directives are contained in include files, they must satisfy the same conditions: There must be no unmatched conditional-compilation directives at the end of the include file. |
| 73 | + |
| 74 | + Macro replacement is performed within the part of the command line that follows an `#elif` command, so a macro call can be used in the *constant-expression*. |
| 75 | + |
| 76 | + The preprocessor selects one of the given occurrences of *text* for further processing. A block specified in *text* can be any sequence of text. It can occupy more than one line. Usually *text* is program text that has meaning to the compiler or the preprocessor. |
| 77 | + |
| 78 | + The preprocessor processes the selected *text* and passes it to the compiler. If *text* contains preprocessor directives, the preprocessor carries out those directives. Only text blocks selected by the preprocessor are compiled. |
| 79 | + |
| 80 | + The preprocessor selects a single *text* item by evaluating the constant expression following each `#if` or `#elif` directive until it finds a true (nonzero) constant expression. It selects all text (including other preprocessor directives beginning with **#**) up to its associated `#elif`, `#else`, or `#endif`. |
| 81 | + |
| 82 | + If all occurrences of *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 *constant-expression* in the `#if` block are false, no text block is selected. |
| 83 | + |
| 84 | + The *constant-expression* is an integer constant expression with these additional restrictions: |
| 85 | + |
| 86 | +- Expressions must have integral type and can include only integer constants, character constants, and the **defined** operator. |
| 87 | + |
| 88 | +- The expression cannot use `sizeof` or a type-cast operator. |
| 89 | + |
| 90 | +- The target environment may not be able to represent all ranges of integers. |
| 91 | + |
| 92 | +- The translation represents type `int` the same as type **long**, and `unsigned int` the same as `unsigned long`. |
| 93 | + |
| 94 | +- The translator 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. |
| 95 | + |
| 96 | +- The expression must not perform any environmental inquiries and must remain insulated from implementation details on the target computer. |
| 97 | + |
| 98 | + The preprocessor operator **defined** can be used in special constant expressions, as shown by the following syntax: |
| 99 | + |
| 100 | + defined( `identifier` ) |
| 101 | + |
| 102 | + defined `identifier` |
| 103 | + |
| 104 | + This constant expression is considered true (nonzero) if the *identifier* is currently defined; otherwise, the condition is false (0). An identifier defined as empty text is considered defined. The **defined** directive can be used in an `#if` and an `#elif` directive, but nowhere else. |
| 105 | + |
| 106 | + In the following example, the `#if` and `#endif` directives control compilation of one of three function calls: |
| 107 | + |
| 108 | +``` |
| 109 | +#if defined(CREDIT) |
| 110 | + credit(); |
| 111 | +#elif defined(DEBIT) |
| 112 | + debit(); |
| 113 | +#else |
| 114 | + printerror(); |
| 115 | +#endif |
| 116 | +``` |
| 117 | + |
| 118 | + The function call to `credit` is compiled if the identifier `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 and C++ because their cases are different. |
| 119 | + |
| 120 | + The conditional compilation statements in the following example assume a previously defined symbolic constant named `DLEVEL`. |
| 121 | + |
| 122 | +``` |
| 123 | +#if DLEVEL > 5 |
| 124 | + #define SIGNAL 1 |
| 125 | + #if STACKUSE == 1 |
| 126 | + #define STACK 200 |
| 127 | + #else |
| 128 | + #define STACK 100 |
| 129 | + #endif |
| 130 | +#else |
| 131 | + #define SIGNAL 0 |
| 132 | + #if STACKUSE == 1 |
| 133 | + #define STACK 100 |
| 134 | + #else |
| 135 | + #define STACK 50 |
| 136 | + #endif |
| 137 | +#endif |
| 138 | +#if DLEVEL == 0 |
| 139 | + #define STACK 0 |
| 140 | +#elif DLEVEL == 1 |
| 141 | + #define STACK 100 |
| 142 | +#elif DLEVEL > 5 |
| 143 | + display( debugptr ); |
| 144 | +#else |
| 145 | + #define STACK 200 |
| 146 | +#endif |
| 147 | +``` |
| 148 | + |
| 149 | + The first `#if` block 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 #**else** are processed. |
| 150 | + |
| 151 | + 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 |
| 152 | + |
| 153 | +``` |
| 154 | +#elif DLEVEL > 5 |
| 155 | +display(debugptr); |
| 156 | +``` |
| 157 | + |
| 158 | + is compiled and `STACK` is not defined. |
| 159 | + |
| 160 | + A common use for conditional compilation is to prevent multiple inclusions of the same header file. In C++, where classes are often defined in header files, constructs like the following can be used to prevent multiple definitions: |
| 161 | + |
| 162 | +``` |
| 163 | +/* EXAMPLE.H - Example header file */ |
| 164 | +#if !defined( EXAMPLE_H ) |
| 165 | +#define EXAMPLE_H |
| 166 | + |
| 167 | +class Example |
| 168 | +{ |
| 169 | +... |
| 170 | +}; |
| 171 | + |
| 172 | +#endif // !defined( EXAMPLE_H ) |
| 173 | +``` |
| 174 | + |
| 175 | + The preceding code checks to see if the symbolic constant `EXAMPLE_H` is defined. If so, the file has already been included and need not be reprocessed. If not, the constant `EXAMPLE_H` is defined to mark EXAMPLE.H as already processed. |
| 176 | + |
| 177 | +## See Also |
| 178 | + [Preprocessor Directives](../VS_visualcpp/Preprocessor-Directives.md) |
0 commit comments