条件包含
预处理器支持源文件的各个部分的条件编译。此行为由 #if 、 #else 、 #elif 、 #ifdef 、 #ifndef 及 #endif 指令控制。
语法
 #if 表达式
 | 
|||||||||
 #ifdef 标识符
 | 
|||||||||
 #ifndef 标识符
 | 
|||||||||
 #elif 表达式
 | 
|||||||||
 #else
 | 
|||||||||
 #endif
 | 
|||||||||
解释
条件预处理块以 #if 、 #ifdef 或 #ifndef 指令开始,然后可选地包含任意数量的 #elif 指令,然后可选地包含至多一个 #else 指令,并以 #endif 指令结束。任何内部条件预处理块都是分开处理的。
每个 #if 、 #elif 、 #else 、 #ifdef 及 #ifndef 指令控制到首个不属于任何内部条件预处理块的 #elif 、 #else 、 #endif 指令为止的代码块。
#if 、 #ifdef 及 #ifndef 指令测试指定条件(见下文),如果指定的条件求值为 true ,则编译控制的代码块。这种情况下忽略后续的 #else 和 #elif 指令。反之,如果指定的条件求值为 false ,则跳过其所控制的代码块,并处理后续的 #else 或 #elif 指令(若存在)。在前一情况下,无条件编译 #else 指令控制的代码块。在后一情况下, #elif 指令的作用就像是一个 #if 指令:检查条件,基于结果编译或跳过控制的代码块,然后在后一情况下处理后续的 #elif 和 #else 指令。条件预处理块以 #endif 指令终止。
条件求值
#if, #elif
表达式 是常量表达式,仅使用常量和用 #define 指令定义的标识符。任何非常量,未以 #define 指令定义的标识符,求值为0。
表达式可以含有形式为 defined 标识符 或 defined (标识符) 的一元运算符,若用 
#define 指令定义了该 标识符 ,则返回 1 ,否则返回 0 。若 表达式 求值为非零值,则包含该控制代码块并跳过其他。若所用的任何标识符不是常量,则用 0 替换它。
| 
 预处理器语境中,   | 
(C23 起) | 
注: DR 412 前,“#if cond1 ... #elif cond2”和“#if cond1 ... #else”后面跟着“#if cond3”是不同的,因为当 cond1 为真时第二个 #if 将被跳过,且 cond3 并不需要是良构的,而 #elif 中的 cond2 则必须是合法的表达式。 DR 412 开始,引领跳过的代码块的 #elif 也被跳过。
#ifdef, #ifndef
检查是否用 #define 指令定义了标识符。
#ifdef 标识符 本质上等价于 #if defined 标识符 。
#ifndef 标识符 本质上等价于 #if !defined 标识符 。
示例
输出:
1: yes 2: yes 3: yes
缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C 标准。
| DR | 应用于 | 出版时的行为 | 正确行为 | 
|---|---|---|---|
| DR 412 | C++14 |  要求失败的 #elif 中的表达式合法
 | 
 跳过失败的 #elif
 | 
引用
- C17 standard (ISO/IEC 9899:2018):
 
- 6.10.1 Conditional inclusion (p: 118-119)
 
- C11 standard (ISO/IEC 9899:2011):
 
- 6.10.1 Conditional inclusion (p: 162-164)
 
- C99 standard (ISO/IEC 9899:1999):
 
- 6.10.1 Conditional inclusion (p: 147-149)
 
- C89/C90 standard (ISO/IEC 9899:1990):
 
- 3.8.1 Conditional inclusion