条件包含
预处理器支持源文件部分内容的条件编译。此行为由 #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++ 文档,关于 条件包含
|