Conditional inclusion
       预处理器支持对源文件部分内容进行条件编译。该行为由
       
        #if
       
       、
       
        #else
       
       、
       
        #elif
       
       、
       
        #ifdef
       
       、
       
        #ifndef
       
       
        
         、
         
          #elifdef
         
         、
         
          #elifndef
         
        
        
         
          (C23起)
         
        
       
       和
       
        #endif
       
       指令控制。
      
| 目录 | 
语法
| 
          
           #if
          
         表达式 | |||||||||
| 
          
           #ifdef
          
         标识符 | |||||||||
| 
          
           #ifndef
          
         标识符 | |||||||||
| 
          
           #elif
          
         表达式 | |||||||||
| 
          
           #elifdef
          
         标识符 | (自 C23 起) | ||||||||
| 
          
           #elifndef
          
         标识符 | (自 C23 起) | ||||||||
| 
          
           #else
          
          | |||||||||
| 
          
           #endif
          
          | |||||||||
说明
       条件预处理块以
       
        #if
       
       、
       
        #ifdef
       
       或
       
        #ifndef
       
       指令开始,随后可选择包含任意数量的
       
        #elif
       
       
        
         、
         
          #elifdef
         
         或
         
          #elifndef
         
        
        
         
          (C23起)
         
        
       
       指令,然后最多包含一个
       
        #else
       
       指令,并以
       
        #endif
       
       指令终止。所有内部条件预处理块都会独立处理。
      
       每个
       
        #if
       
       、
       
        #ifdef
       
       、
       
        #ifndef
       
       、
       
        #elif
       
       
        
         、
         
          #elifdef
         
         、
         
          #elifndef
         
        
        
         
          (C23 起)
         
        
       
       和
       
        #else
       
       指令控制代码块,直到遇到第一个不属于任何内部条件预处理块的
       
        #elif
       
       
        
         、
         
          #elifdef
         
         、
         
          #elifndef
         
        
        
         
          (C23 起)
         
        
       
       、
       
        #else
       
       或
       
        #endif
       
       指令。
      
       
        #if
       
       、
       
        #ifdef
       
       和
       
        #ifndef
       
       指令测试指定条件(见下文),若评估为真,则编译受控代码块。此时后续的
       
        #else
       
       
        
         、
         
          #elifdef
         
         、
         
          #elifndef
         
         、
        
        
         
          (since C23)
         
        
       
       及
       
        #elif
       
       指令将被忽略。否则,若指定条件评估为假,则跳过受控代码块并处理后续的
       
        #else
       
       
        
         、
         
          #elifdef
         
         、
         
          #elifndef
         
         、
        
        
         
          (since C23)
         
        
       
       或
       
        #elif
       
       指令(若存在)。若后续指令为
       
        #else
       
       ,则
       
        #else
       
       指令控制的代码块将被无条件编译。否则,
       
        #elif
       
       
        
         、
         
          #elifdef
         
         或
         
          #elifndef
         
        
        
         
          (since C23)
         
        
       
       指令的行为与
       
        #if
       
       指令类似:检查条件,根据结果编译或跳过受控代码块,并在后一种情况下处理后续的
       
        #elif
       
       
        
         、
         
          #elifdef
         
         、
         
          #elifndef
         
         、
        
        
         
          (since C23)
         
        
       
       和
       
        #else
       
       指令。条件预处理块由
       
        #endif
       
       指令终止。
      
条件求值
#if, #elif
该 表达式 是常量表达式,仅使用 常量 和通过 #define 指令定义的标识符。任何非字面量且未通过 #define 指令定义的标识符,其求值结果为  0  ,但 true 的求值结果为 1 除外 (C23起) 。
       表达式可能包含形式为
       
        defined
       
       
        identifier
       
       或
       
        defined (
       
       
        identifier
       
       
        )
       
       的一元运算符,若该
       
        identifier
       
       已通过
       
        
         #define
        
       
       指令定义则返回
       
        
         
          1
         
        
       
       ,否则返回
       
        
         
         
          0
         
         
        
       
       。
       
        
         在此上下文中,
         
          
           __has_include
          
         
         、
         
          
           __has_embed
          
         
         和
         
          
           __has_c_attribute
          
         
         会被视为已定义的宏名称。
        
        
         
          (C23 起)
         
        
       
       若
       
        expression
       
       求值为非零值,则受控代码块会被包含,否则被跳过。若任何使用的标识符不是常量,则会被替换为
       
        
         
         
          0
         
         
        
       
       。
      
| 
          在预处理器指令的上下文中,
           | (since C23) | 
       注意:在
       
        DR 412
       
       之前,
       
        #if
        
         cond1
        
       
       ...
       
        #elif
        
         cond2
        
       
       与
       
        #if
        
         cond1
        
       
       ...
       
        #else
       
       后接
       
        #if
        
         cond3
        
       
       有所不同,因为如果
       
        
         cond1
        
       
       为真,第二个
       
        #if
       
       会被跳过,此时
       
        
         cond3
        
       
       不需要是合法表达式,而
       
        #elif
       
       的
       
        
         cond2
        
       
       必须是合法表达式。自
       
        DR 412
       
       起,导致代码块被跳过的
       
        #elif
       
      
组合指令
检查该标识符是否 被定义为宏名称 。
       
        #ifdef
       
       
        identifier
       
       本质上等同于
       
        #if defined
       
       
        identifier
       
       。
      
       
        #ifndef
       
       
        identifier
       
       本质上等同于
       
        #if !defined
       
       
        identifier
       
       。
      
| 
           
           | (C23 起) | 
注释
       虽然
       
        #elifdef
       
       和
       
        #elifndef
       
       指令的目标是 C23 标准,但实现可能会将它们作为符合规范的扩展向后移植到较旧的语言模式中。
      
示例
#define ABCD 2 #include <stdio.h> int main(void) { #ifdef ABCD printf("1: yes\n"); #else printf("1: no\n"); #endif #ifndef ABCD printf("2: no1\n"); #elif ABCD == 2 printf("2: yes\n"); #else printf("2: no2\n"); #endif #if !defined(DCBA) && (ABCD < 2 * 4 - 3) printf("3: yes\n"); #endif // C23 directives #elifdef/#elifndef #ifdef CPU printf("4: no1\n"); #elifdef GPU printf("4: no2\n"); #elifndef RAM printf("4: yes\n"); // selected in C23 mode, may be selected in pre-C23 mode #else printf("4: no3\n"); // may be selected in pre-C23 mode #endif }
可能的输出:
1: yes 2: yes 3: yes 4: yes
缺陷报告
下列行为变更缺陷报告被追溯应用于先前发布的C语言标准。
| 缺陷报告 | 适用范围 | 发布时行为 | 正确行为 | 
|---|---|---|---|
| DR 412 | C89 | 要求失败的 
          #elif
         表达式必须有效 | 失败的 
          #elif
         会被跳过 | 
参考文献
- C23 标准 (ISO/IEC 9899:2024):
- 
         - 6.10.1 条件包含 (p: TBD)
 
- C17 标准 (ISO/IEC 9899:2018):
- 
         - 6.10.1 条件性包含 (页码: 118-119)
 
- C11 标准 (ISO/IEC 9899:2011):
- 
         - 6.10.1 条件包含 (p: 162-164)
 
- C99标准(ISO/IEC 9899:1999):
- 
         - 6.10.1 条件包含(页码:147-149)
 
- C89/C90 标准 (ISO/IEC 9899:1990):
- 
         - 3.8.1 条件包含
 
参见
| 
          
           
            C++ 文档
           
          
          关于
          
           
            条件包含
           
          
          |