Constant expressions
多种表达式类型被称为 常量表达式 。
目录 |
预处理器常量表达式
在
#if
或
#elif
之后的表达式必须展开为
字符常量在
#if
表达式中求值时,可能被解释为源字符集、执行字符集或其他实现定义的字符集。
|
|
(C99起) |
整型常量表达式
整数常量表达式是由仅包含以下内容组成的表达式:
- 除 赋值 、 自增/自减 、 函数调用 或 逗号 运算符之外的 运算符 ,但 强制转换 运算符仅可将算术类型转换为整型,除非它们是 sizeof , _Alignof (C11起) (C23前) , alignas (C23起) 或 typeof/typeof_unqual (C23起) 运算符的操作数。
- 整型常量
- 枚举常量
- 字符常量
- 浮点常量 ,但仅当它们被立即用作强制转换到整型的操作数时
-
操作数不是 VLA 的
sizeof运算符 (其操作数不是 VLA) (C99起)
|
(C11起) |
|
(since C23) |
整数常量表达式在编译时进行求值。以下上下文要求被称为 整数常量表达式 的表达式:
|
(since C99) |
|
(since C11) |
|
(since C23) |
静态初始化器
用于具有静态和线程局部 存储期 对象 初始化器 中的表达式 或使用 constexpr 存储类说明符声明的表达式 (C23起) ,必须是字符串字面量或满足以下条件之一的表达式:
| (C11 起) |
|
(C23 起) |
|
5)
一个
命名常量
,即满足以下条件的标识符:
.
成员访问运算符的后缀表达式。
6)
一个
复合字面量常量
,即:
结构体/联合常量
分别是具有结构体/联合类型的命名常量或复合字面量常量。若成员访问运算符
|
(C23 起) |
与整型常量表达式不同,静态初始化表达式不要求在编译时求值;编译器有权将此类初始化器转换为在程序启动前调用的可执行代码。
static int i = 2 || 1 / 0; // 将 i 初始化为值 1
|
本节内容不完整
原因:缺少其他小型示例 |
浮点静态初始化表达式的值精度绝不会低于运行时执行同一表达式的值,但可能更高。
浮点常量表达式
不在静态初始化器中使用的浮点类型算术常量表达式始终如同在运行时求值,并受 当前舍入方向 影响(若 FENV_ACCESS 处于开启状态),且错误报告遵循 math_errhandling 的规定。
void f(void) { #pragma STDC FENV_ACCESS ON static float x = 0.0 / 0.0; // 静态初始化器:不会引发异常 float w[] = { 0.0 / 0.0 }; // 引发异常 float y = 0.0 / 0.0; // 引发异常 double z = 0.0 / 0.0; // 引发异常 }
注释
如果表达式求值结果无法由其类型表示,则不能用作常量表达式。
实现可以接受其他形式的常量表达式。但这些常量表达式不被视为整型常量表达式、算术常量表达式或地址常量表达式,因此不能用于需要这些类型常量表达式的上下文。例如, int arr [ ( int ) + 1.0 ] ; 声明了一个可变长度数组。
参考文献
- C23 标准 (ISO/IEC 9899:2024):
-
- 6.6 常量表达式 (p: 95-96)
- 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 常量表达式(页码:95-96)
- C89/C90 标准 (ISO/IEC 9899:1990):
-
- 3.4 常量表达式
另请参阅
|
C++ 文档
关于
常量表达式
|