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