Namespaces
Variants

Scalar initialization

From cppreference.net

初始化 标量类型 的对象时,初始化器必须是单个表达式

标量(包括布尔类型和枚举类型的整型对象、包含复数和虚数的浮点类型、以及包含函数指针的指针类型)的初始化器必须是单个表达式,可选择性地用花括号括起 ,或使用空初始化器 (C23起)

= 表达式 (1)
= { 表达式 } (2)
= { } (3) (C23起)
1,2) 表达式被求值,其值经 如同通过赋值进行的转换 后,成为被初始化对象的初始值。
3) 该对象进行 空初始化 ,即对于算术类型或枚举类型的对象初始化为数值零,对于指针类型的对象初始化为空指针值。

注释

由于按赋值转换规则所适用的准则,在确定要将 表达式 转换为何种类型时,声明类型上的 const volatile 限定符将被忽略。

参见 初始化 了解未使用初始化式时的适用规则。

与所有其他初始化一样,当初始化具有静态或线程局部 存储期 的对象时, 表达式 必须是 常量表达式

表达式 不能是 逗号运算符 (除非使用括号括起),因为顶层的逗号会被解释为下一个声明符的开始。

当初始化浮点类型对象时,对于具有自动 存储期 的对象,所有计算都如同在运行时执行,并受 当前舍入模式 影响;浮点错误将按照 math_errhandling 的规定进行报告。对于具有静态和线程局部存储期的对象,计算如同在编译时执行,且不会引发异常:

void f(void)
{
#pragma STDC FENV_ACCESS ON
    static float v = 1.1e75; // 不会引发异常:静态初始化
    float u[] = { 1.1e75 }; // 引发 FE_INEXACT
    float w = 1.1e75;       // 引发 FE_INEXACT
    double x = 1.1e75; // 可能引发 FE_INEXACT(取决于 FLT_EVAL_METHOD)
    float y = 1.1e75f; // 可能引发 FE_INEXACT(取决于 FLT_EVAL_METHOD)
    long double z = 1.1e75; // 不会引发异常(转换是精确的)
}

示例

#include <stdbool.h>
int main(void)
{
    bool b = true;
    const double d = 3.14;
    int k = 3.15; // 从 double 到 int 的转换
    int n = {12}, // 可选花括号
       *p = &n,   // 对自动变量允许使用非常量表达式
       (*fp)(void) = main;
    enum {RED, BLUE} e = RED; // 枚举类型同样属于标量类型
}

参考文献

  • C17 标准 (ISO/IEC 9899:2018):
  • 6.7.9/11 初始化 (p: 101)
  • C11 标准 (ISO/IEC 9899:2011):
  • 6.7.9/11 初始化 (p: 140)
  • C99标准(ISO/IEC 9899:1999):
  • 6.7.8/11 初始化(页:126)
  • C89/C90 标准 (ISO/IEC 9899:1990):
  • 6.5.7 初始化