名稱空間
變體
操作

條件包含

來自 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 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++ 文件 關於 條件包含