条件包含
预处理器支持对源文件部分进行条件编译。此行为由 #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
、(自 C23 起) 和 #elif
指令将被忽略。否则,如果指定的条件评估为假,则跳过受控代码块,并处理后续的 #else
、#elifdef
、#elifndef
、(自 C23 起) 或 #elif
指令(如果有)。如果后续指令为 #else
,则由 #else
指令控制的代码块将无条件编译。否则,#elif
、#elifdef
或 #elifndef
(自 C23 起) 指令的行为就像 #if
指令:检查条件,根据结果编译或跳过受控代码块,如果跳过,则处理后续的 #elif
、#elifdef
、#elifndef
、(自 C23 起) 和 #else
指令。条件预处理块由 #endif
指令终止。
[编辑] 条件评估
[编辑] #if, #elif
表达式 是一个常量表达式,仅使用 常量 和使用 #define 指令定义的标识符。任何不是字面量且未使用 #define 指令定义的标识符都评估为 0 ,除了 true,它评估为 1(自 C23 起).
表达式可以包含 defined
标识符 或 defined (
标识符)
形式的单目运算符,如果 标识符 使用 #define 指令定义,则返回 1,否则返回 0。 在此上下文中,__has_include, __has_embed 和 __has_c_attribute 被视为已定义宏的名称。(自 C23 起) 如果 表达式 评估为非零值,则包含受控代码块,否则跳过。如果使用的任何标识符不是常量,则将其替换为 0.
在预处理器指令的上下文中, |
(自 C23 起) |
注意:直到 DR 412,#if cond1
... #elif cond2
与 #if cond1
... #else
后跟 #if cond3
不同,因为如果 cond1
为真,则第二个 #if
将被跳过,并且 cond3
不需要格式正确,而 #elif
的 cond2
必须是一个有效的表达式。从 DR 412 开始,导致跳过代码块的 #elif
也被跳过。
[编辑] 组合指令
检查标识符是否 被定义为宏名.
#ifdef
标识符 本质上等效于 #if defined
标识符.
#ifndef
标识符 本质上等效于 #if !defined
标识符.
|
(自 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 | 应用于 | 发布时的行为 | 正确的行为 |
---|---|---|---|
DR 412 | C89 | 失败的 #elif 的表达式需要有效 |
失败的 #elif 被跳过 |
[编辑] 参考文献
- C23 标准 (ISO/IEC 9899:2024)
- 6.10.1 条件包含 (p: TBD)
- C17 标准 (ISO/IEC 9899:2018)
- 6.10.1 条件包含 (p: 118-119)
- C11 标准 (ISO/IEC 9899:2011)
- 6.10.1 条件包含 (p: 162-164)
- C99 标准 (ISO/IEC 9899:1999)
- 6.10.1 条件包含 (p: 147-149)
- C89/C90 标准 (ISO/IEC 9899:1990)
- 3.8.1 条件包含
[编辑] 另请参阅
C++ 文档 关于 条件包含
|