命名空间
变体
操作

常量表达式

来自 cppreference.cn
< c‎ | language

几种不同类型的表达式被称为 常量表达式

目录

[编辑] 预处理器常量表达式

紧跟在 #if#elif 之后的表达式必须展开为

字符常量在 #if 表达式中求值时,可以根据源字符集、执行字符集或其他实现定义的字符集进行解释。

#if 表达式中的整数算术运算使用 intmax_t (对于有符号类型) 和 uintmax_t (对于无符号类型) 的语义执行。

(C99 起)

[编辑] 整型常量表达式

整型常量表达式是由以下内容组成的表达式:

  • _Alignof(C23 前)alignas(C23 起) 运算符
(C11 起)
  • 命名和复合字面量常量,它们是整型类型或算术类型,并且是类型转换运算符的直接操作数
(C23 起)

整型常量表达式在编译时求值。以下上下文需要被称为 整型常量表达式 的表达式:

  • 位域的大小。
  • 枚举常量的值
  • switch 语句的 case 标签
  • 非 VLA 数组的大小
  • 整型到指针的隐式 转换
  • 数组设计器中的索引
(C99 起)
  • _Static_assert 的第一个参数
  • _Alignof 的整型参数
(C11 起)
  • 位精确整数类型 (_BitInt(N)) 的位数 N
(C23 起)

[编辑] 静态初始化器

用于具有静态和 thread_local 存储期限 的对象 或用 constexpr 存储类说明符声明的对象(C23 起) 的初始化器中的表达式,必须是字符串字面量或可以是以下之一的表达式

1) 算术常量表达式,它是任何算术类型的表达式,由以下内容组成:
(C11 起)
  • 算术类型的命名或复合字面量常量
(C23 起)
2) 空指针常量 (例如 NULL)
3) 地址常量表达式,它是
  • 空指针
  • 左值,指示具有静态 存储期限 的对象或函数指示符,转换为指针的方式可以是
  • 使用一元取地址运算符
  • 通过将整型常量转换为指针
  • 通过数组到指针或函数到指针的隐式 转换
4) 某种完整对象类型的 地址常量表达式 ,加上或减去一个 整型常量表达式
5) 命名常量 ,它是指,一个标识符,它是
  • 枚举常量
  • 预定义的常量 (true、false 或 nullptr 之一)
  • 用存储类说明符 constexpr 声明并具有对象类型
或者是一个后缀表达式,它将 . 成员访问运算符应用于结构体或联合类型的命名常量,即使是递归的。
6) 复合字面量常量 ,它是
  • 复合字面量,具有存储类说明符 constexpr
  • 一个后缀表达式,它将 . 成员访问运算符应用于结构体或联合类型的复合字面量常量,即使是递归的。

结构体或联合体常量 分别是具有结构体或联合体类型的命名常量或复合字面量常量。如果成员访问运算符 . 访问联合体常量的成员,则访问的成员应与联合体常量的初始化器初始化的成员相同。

(C23 起)
7) 实现接受的其他形式之一的常量表达式。

与整型常量表达式不同,静态初始化器表达式不一定需要在编译时求值;编译器可以自由地将此类初始化器转换为在程序启动前调用的可执行代码。

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
}

[编辑] 注释

如果表达式求值得到的值不能用其类型表示,则不能用作常量表达式。

实现可能会接受其他形式的常量表达式。但是,这些常量表达式不被视为整型常量表达式、算术常量表达式或地址常量表达式,因此不能在需要这些类型常量表达式的上下文中使用。例如,int arr[(int)+1.0]; 声明了一个 VLA。

[编辑] 参考文献

  • C23 标准 (ISO/IEC 9899:2024)
  • 6.6 常量表达式 (p: TBD)
  • 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 常量表达式 (p: 95-96)
  • C89/C90 标准 (ISO/IEC 9899:1990)
  • 3.4 常量表达式

[编辑] 参见

C++ 文档,关于 常量表达式