Constant expressions
常量表达式
几种表达式被称为常量表达式。
预处理器常量表达式
#if 或 #elif 后面的表达式必须扩展为。
- 除赋值,增量,减量,函数调用或逗号之外的其他操作符,其参数是预处理常量表达式
当在#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) |
---|
整数常量表达式
一个整型常量表达式是表达式。
- 除赋值,递增,递减,函数调用或逗号以外的其他操作符,除了转换操作符只能将算术类型转换为整数类型
_Alignof operators | (since C11) |
---|
- _Alignof operators
(since C11)
整数常量表达式在编译时进行评估。以下上下文需要称为整型常量表达式的表达式':
- 位字段的大小。
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
(since C11)
静态初始化器
在具有 static 和 thread_local 存储持续时间的对象的初始化器中使用的表达式必须是可能是以下某个表达式的表达式。
1)算术常数表达式,它是由任意算术类型组成的表达式
- 除赋值,增量,减量,函数调用或逗号以外的其他操作符,除了转换操作符必须将算术类型转换为其他算术类型
_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):