命名空间
变体
操作

条件包含

来自 cppreference.com

预处理器支持对源文件部分进行条件编译。此行为由 #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.

在预处理器指令的上下文中,__has_c_attribute 表达式检测给定属性标记是否受支持以及其支持的版本。请参阅 属性测试.

(自 C23 起)

注意:直到 DR 412#if cond1 ... #elif cond2#if cond1 ... #else 后跟 #if cond3 不同,因为如果 cond1 为真,则第二个 #if 将被跳过,并且 cond3 不需要格式正确,而 #elifcond2 必须是一个有效的表达式。从 DR 412 开始,导致跳过代码块的 #elif 也被跳过。

[编辑] 组合指令

检查标识符是否 被定义为宏名.

#ifdef 标识符 本质上等效于 #if defined 标识符.

#ifndef 标识符 本质上等效于 #if !defined 标识符.

#elifdef 标识符 本质上等效于 #elif defined 标识符.

#elifndef 标识符 本质上等效于 #elif !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++ 文档 关于 条件包含