條件包含
預處理器支援對原始檔的部分進行條件編譯。此行為由 #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 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++ 文件 關於 條件包含
|