常量表达式
来自cppreference.com
表达式的数种变体被称为常量表达式。
预处理器常量表达式
后随 #if 或 #elif 的表达式必须展开成
字符常量在 #if
表达式中求值时,可能以源字符集、执行字符集或某个其他实现定义字符集转译。
(C99 起) |
整数常量表达式
整数常量表达式是仅由下列内容组成的表达式
- 赋值、自增、自减、函数调用或逗号以外的运算符,除了转型运算符只能转型算术类型为整数类型
- 整数常量
- 枚举常量
- 字符常量
- 浮点常量,但仅若立即以之为转型到整数类型的操作数
- 操作数非 VLA 的 (C99 起)
sizeof
运算符
|
(C11 起) |
整数常量表达式在编译时求值。下列语境要求被称为整数常量表达式的表达式:
|
(C99 起) |
|
(C11 起) |
静态初始化器
拥有静态和线程局域存储期的对象初始化器中使用的表达式必须是下列表达式之一
1) 算术常量表达式,即由下列内容构成的任何算术类型表达式
|
(C11 起) |
2) 空指针常量 NULL
4) 某完整对象类型的地址常量表达式加或减一个整数常量表达式
5) 实现所接受的其他形式之一的常量表达式。
不同于整数常量表达式,不要求静态初始化器在编译时求值;编译器有将这种初始化器转变为在程序启动前调用的可执行代码的自由。
static int i = 2 || 1 / 0; // 初始化 i 为值 1
本节未完成 原因:其他小示例 |
浮点静态初始化器的值的精度决不低于在运行时执行的同一表达式,但可以高于后者。
浮点常量表达式
不用于静态初始化器中的浮点类型的算术常量表达式,始终如同在运行时求值,受当前舍入影响(若 FENV_ACCESS 为 ON ),并报告 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]; 声明一个 VLA。
引用
- C17 标准(ISO/IEC 9899:2018):
- 6.6 Constant expressions (第 76-77 页)
- C11 标准(ISO/IEC 9899:2011):
- 6.6 Constant expressions (第 106-107 页)
- C99 标准(ISO/IEC 9899:1999):
- 6.6 Constant expressions (第 95-96 页)
- C89/C90 标准(ISO/IEC 9899:1990):
- 3.4 CONSTANT EXPRESSIONS