The #if directive begins a region of conditional compilation, that is, a region within a source file where preprocessor directives determine whether the code in the region is compiled. A conditional region starts with #ifdef, #ifndef, or #if and ends with #endif. Each region can have any number of #elif directives and an optional #else directive after all the #elif directives. The basic form to use is: #if defined(_ _win32_ _) const char os[] = "Microsoft Windows"; #elif defined(__linux__) or defined(_ _unix_ _) const char os[] = "UNIX (or variant)"; #elif defined(_ _vms_ _) const char os[] = "VMS"; #else const char os[] = "(unknown)"; #endif Macros in the directive argument are expanded, except for the operands of the defined operator. The constant expression is evaluated, and if the result is nonzero, the #if condition is true, and the code in the region that immediately follows is compiled. The region ends with #else, #elif, or #endif. If the #if expression is false, the condition for the next #elif is evaluated, and if that expression is true, its region is compiled, and so on. If all #elif expressions are false, and #else is present, its region is compiled. Conditional processing ends with the corresponding #endif directive. Conditionals can be nested. Within an inner region, the preprocessor keeps track of conditional directives even if the region is not being compiled, so conditional directives can be properly matched. The #if and #elif directives take a single parameter, a constant expression. The expression differs slightly from non-preprocessor constant expressions:
Conditional directives are most often used to guard header files from multiple inclusion. All the standard headers are guarded, so including them more than once has no harmful effects. This is important because an implementation might include one header in another header. For example, <map> might include <utility> to get the declaration for the pair<> template. If you explicitly #include <map> and #include <utility>, you might end up including <utility> more than once. Another common use is for system- or compiler-specific code. Every compiler predefines one or more macros to identify the compiler and possibly the host operating system (such as _ _linux_ _ or _ _GNUC_ _). Consult your compiler's documentation to learn which macro names are predefined. ExamplesExample 11-4 shows one way to nest conditional directives. Example 11-4. Nesting conditional directives#define zero zero // Identifiers are converted to 0. #define one true // Bool expressions are promoted to int. #if one // This region is compiled. #if zero This region can contain erroneous C++ code. The code is not compiled, so the errors do not matter. #else // This #else matches the inner #if. // This region is compiled. const int zero = 0; #endif // This #endif matches the inner #if. int x = zero; #else This #else matches the outer #if. Because the #if condition was true, the #else region is not compiled. #endif You can guard your own headers by using conditional directives to define a guard macro and using the guard macro to ensure the file's contents are compiled only when the macro is not defined, as shown in Example 11-5. Example 11-5. Guarding a header against multiple inclusion// In the header file employee.h #ifndef EMPLOYEE_H #define EMPLOYEE_H // Thus, the entire contents of the file are compiled only when EMPLOYEE_H is not // defined. The first time the file is #included, the macro is not defined, in // which case it is immediately defined. The second and subsequent times the same // header is included in the same source file; the macro and conditional // directives ensure that the entire file is skipped. class employee { ... }; #endif // End of employee.h See Also#elif directive, #else directive, #endif directive, #ifdef directive, #ifndef directive |