常量表达式
来自cppreference.com
表达式的数种变体被称为常量表达式。
预处理器常量表达式
#if
或 #elif
之后的表达式必须展开成
字符常量在 #if
表达式中求值时,可能以源字符集、执行字符集或某个其他实现定义字符集转译。
(C99 起) |
整数常量表达式
整数常量表达式是仅由下列内容组成的表达式
- 赋值、自增、自减、函数调用或逗号以外的运算符,但转型运算符只能转型算术类型为整数类型,除非它们是 sizeof、_Alignof (C11 起) 或 typeof/typeof_unqual (C23 起) 运算符的操作数的一部分。
- 整数常量
- 枚举常量
- 字符常量
- 浮点常量,但仅当其作为向整数类型转型的直接操作数
- 操作数非 VLA 的 (C99 起)
sizeof
运算符
|
(C11 起) |
|
(C23 起) |
整数常量表达式在编译时求值。下列语境要求被称为整数常量表达式的表达式:
|
(C99 起) |
|
(C11 起) |
|
(C23 起) |
静态初始化式
拥有静态和线程局域存储期或者以存储类说明符 constexpr 所声明 (C23 起)的对象的初始化式中使用的表达式,必须是下列表达式之一
2) 空指针常量(比如 NULL)
4) 某完整对象类型的地址常量表达式加或减一个整数常量表达式
5) 具名常量,为以下标识符
. 的后缀表达式。6) 复合字面量常量,为
结构体或联合体常量分别是具有结构体或联合体类型的具名常量或复合字面量常量。如果成员访问运算符 |
(C23 起) |
7) 实现所接受的其他形式之一的常量表达式。
不同于整数常量表达式,不要求静态初始化器在编译时求值;编译器有将这种初始化器转变为在程序启动前调用的可执行代码的自由。
static int i = 2 || 1 / 0; // 初始化 i 为值 1
本节未完成 原因:其他小示例 |
浮点静态初始化器的值的精度决不低于在运行时执行的同一表达式,但可以高于后者。
浮点常量表达式
不用于静态初始化器中的浮点类型的算术常量表达式,始终如同在运行时求值,受当前舍入影响(若 Template:c/preprocessor/impl 为 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。
引用
- C23 标准(ISO/IEC 9899:2024):
- 6.6 Constant expressions (第 TBD 页)
- 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