幾種表達式被稱為常量表達式。
預處理器常量表達式
#if 或 #elif 後面的表達式必須擴充為。
除指派,增量,減量,函數調用或逗号之外的其他操作符,其參數是預處理常量表達式
整數常量
字元常量
特殊的預處理器操作員 defined
當在#if表達式中計算字元常量時,可以在源字元集,執行字元集或其他一些實作定義的字元集中解釋字元常量。
Integer arithmetic in #if-expressions is performed using the semantics of intmax_t for signed types and uintmax_t for unsigned types.(since C99)
整數常量表達式
一個整型常量表達式是表達式。
除指派,遞增,遞減,函數調用或逗号以外的其他操作符,除了轉換操作符隻能将算術類型轉換為整數類型
整數常量
枚舉常量
字元常量
浮點型常量,但前提是它們立即用作轉換為整數類型的操作數
操作數不是VLA的操作符的大小(自C99起)
_Alignof operators(since C11)
_Alignof operators
(since C11)
整數常量表達式在編譯時進行評估。以下上下文需要稱為整型常量表達式的表達式':
位字段的大小。
枚舉常量的值
caseswitch語句的标簽
非VLA(自C99以來)陣列的大小
整數指針隐式轉換。
The index in an array designator(since C99)
數組訓示符中的索引
(since C99)
The first argument of _Static_assert The integer argument of _Alignas(since C11)
第一個論點 _Static_assert
整數參數 _Alignas
(since C11)
靜态初始化器
在具有 static 和 thread_local 存儲持續時間的對象的初始化器中使用的表達式必須是可能是以下某個表達式的表達式。
1)算術常數表達式,它是由任意算術類型組成的表達式
除指派,增量,減量,函數調用或逗号以外的其他操作符,除了轉換操作符必須将算術類型轉換為其他算術類型
整數常量
浮點常量
枚舉常量
字元常量
操作數不是VLA的操作符的大小(自C99起)
_Alignof operators(since C11)
_Alignof 操作符
(since C11)
2)空指針常量 NULL
3)位址常量表達式,這是
一個空指針
左值指定一個靜态存儲持續時間的對象或一個函數訓示符,并轉換為指針通過使用一進制位址運算符
通過将一個整型常量轉換為一個指針
通過數組到指針或函數到指針的隐式轉換
4)位址常量表達一些完整的對象類型,加或減一個整型常量表達式
與整型常量表達式不同,靜态初始化表達式不需要在編譯時進行評估; 編譯器可以自由地将這些初始化程式轉換為在程式啟動之前調用的可執行代碼。
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}
注意
如果一個表達式的計算結果不能用它的類型表示,那麼它就不能用作常量表達式。
參考
C11 standard (ISO/IEC 9899:2011):6.6 Constant expressions (p: 106-107)
C99 standard (ISO/IEC 9899:1999):6.6 Constant expressions (p: 95-96)
C89/C90 standard (ISO/IEC 9899:1990):3.4 CONSTANT EXPRESSIONS