常量表達式
來自 cppreference.com
有幾種表示式被稱為常量表達式
目錄 |
[編輯] 預處理常量表達式
#if
或 #elif
後面的表示式必須展開為
字元常量在 #if
表示式中求值時,可以按源字元集、執行字元集或某些其他實現定義的字元集進行解釋。
(C99 起) |
[編輯] 整型常量表達式
整型常量表達式是由以下內容組成的表示式:
- 除了賦值、增量、減量、函式呼叫或逗號之外的運算子,但 強制轉換 運算子只能將算術型別轉換為整型,除非它們是 sizeof 、_Alignof(C11 起)(C23 止)、alignas(C23 起) 或 typeof/typeof_unqual(C23 起) 運算子的運算元的一部分。
- 整型常量
- 列舉常量
- 字元常量
- 浮點常量,但僅當它們直接用作向整型轉換的強制轉換的運算元時
-
sizeof
運算子 ,其運算元不是 VLA(C99 起)
|
(C11 起) |
|
(自 C23 起) |
整型常量表達式在編譯時求值。以下上下文需要被稱為整型常量表達式的表示式:
|
(C99 起) |
|
(C11 起) |
|
(自 C23 起) |
[編輯] 靜態初始化器
用於具有靜態和 thread_local 儲存期的物件的初始化器中的表示式,或用 constexpr 儲存類說明符宣告的表示式(C23 起)必須是字串字面量或以下表達式之一:
1) 算術常量表達式,它是任何算術型別的表示式,由以下內容組成:
(C11 起) |
|
(自 C23 起) |
2) 空指標常量(例如 NULL)
4) 某些完整物件型別的地址常量表達式,加上或減去整型常量表達式
5) 命名常量,即一個識別符號,它是一個
. 成員訪問運算子應用於結構或聯合型別的命名常量,甚至是遞迴的。6) 複合字面常量,即
結構或聯合常量分別是具有結構或聯合型別的命名常量或複合字面常量。如果成員訪問運算子 |
(自 C23 起) |
7) 實現接受的其他形式的常量表達式。
與整型常量表達式不同,靜態初始化器表示式不需要在編譯時求值;編譯器可以自由地將此類初始化器轉換為在程式啟動之前呼叫的可執行程式碼。
static int i = 2 || 1 / 0; // initializes i to value 1
本節不完整 原因:其他小示例 |
浮點靜態初始化器的值永遠不會比執行時執行的相同表示式的值精度低,但可能更高。
[編輯] 浮點常量表達式
未在靜態初始化器中使用的浮點型別算術常量表達式始終像在執行時一樣求值,並受當前舍入的影響(如果 FENV_ACCESS 已開啟),並按 math_errhandling 中指定報告錯誤。
void f(void) { #pragma STDC FENV_ACCESS ON static float x = 0.0 / 0.0; // static initializer: does not raise an exception float w[] = { 0.0 / 0.0 }; // raises an exception float y = 0.0 / 0.0; // raises an exception double z = 0.0 / 0.0; // raises an exception }
[編輯] 備註
如果表示式求值為其型別無法表示的值,則不能將其用作常量表達式。
實現可以接受其他形式的常量表達式。但是,這些常量表達式不被視為整型常量表達式、算術常量表達式或地址常量表達式,因此不能在需要這些型別的常量表達式的上下文中使用。例如,int arr[(int)+1.0]; 聲明瞭一個 VLA。
[編輯] 參考
- C23 標準 (ISO/IEC 9899:2024)
- 6.6 常量表達式 (p: 待定)
- C17 標準 (ISO/IEC 9899:2018)
- 6.6 常量表達式 (p: 76-77)
- C11 標準 (ISO/IEC 9899:2011)
- 6.6 常量表達式 (p: 106-107)
- C99 標準 (ISO/IEC 9899:1999)
- 6.6 常量表達式 (p: 95-96)
- C89/C90 標準 (ISO/IEC 9899:1990)
- 3.4 CONSTANT EXPRESSIONS
[編輯] 另請參閱
C++ 文件中的 常量表達式
|