常量表达式

来自cppreference.com
< c‎ | language

表达式的数种变体被称为常量表达式

预处理器常量表达式

后随 #if 或 #elif 的表达式必须展开成

字符常量在 #if 表达式中求值时,可能以源字符集、执行字符集或某个其他实现定义字符集转译。

#if 表达式中,对有符号类型以 intmax_t 的语义,而对无符号类型以 uintmax_t 的语义进行整数算术。

(C99 起)

整数常量表达式

整数常量表达式是仅由下列内容组成的表达式

(C11 起)

整数常量表达式在编译时求值。下列语境要求被称为整数常量表达式的表达式:

(C99 起)
(C11 起)

静态初始化器

拥有静态和线程局域存储期的对象初始化器中使用的表达式必须是下列表达式之一

1) 算术常量表达式,即由下列内容构成的任何算术类型表达式
(C11 起)
2) 空指针常量 NULL
3) 地址常量表达式,即
  • 空指针
  • 指代静态存储期的对象的左值,或函数指代器,通过下列方式之一转换为指针
  • 用一元取址运算符
  • 转型整数常量到指针
  • 数组到指针或函数到指针隐式转换
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

参阅