Namespaces
Variants

Scalar initialization

From zh.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 初始化