Namespaces
Variants

Scalar initialization

From cppreference.net

При инициализации объекта скалярного типа инициализатор должен быть единственным выражением

Инициализатор для скалярного типа (объекта целочисленного типа, включая логические и перечислимые типы, типа с плавающей точкой, включая комплексные и мнимые, и указательного типа, включая указатель на функцию) должен быть единственным выражением, опционально заключенным в фигурные скобки , или пустым инициализатором (начиная с C23) :

= выражение (1)
= { выражение } (2)
= { } (3) (начиная с C23)
1,2) Выражение вычисляется, и его значение, после преобразования как при присваивании к типу объекта, становится начальным значением инициализируемого объекта.
3) Объект пусто инициализируется , т.е. инициализируется нулевым числовым значением для объекта арифметического или перечислимого типа, или нулевым значением указателя для объекта типа указателя.

Примечания

Из-за правил, применяемых к преобразованиям как при присваивании, const и volatile квалификаторы объявленного типа игнорируются при определении типа, к которому следует преобразовать выражение .

См. инициализация для правил, применяемых когда инициализатор не используется.

Как и при всех других инициализациях, expression должно быть constant expression при инициализации объектов со статической или thread-local storage duration .

Выражение expression не может быть оператором запятой (если не заключено в скобки), поскольку запятая на верхнем уровне будет интерпретирована как начало следующего декларатора.

При инициализации объектов типа с плавающей запятой все вычисления для объектов с автоматической длительностью хранения выполняются как бы во время выполнения и подвержены влиянию текущего округления ; ошибки чисел с плавающей запятой регистрируются в соответствии с math_errhandling . Для объектов со статической и thread-local длительностью хранения вычисления выполняются как бы во время компиляции, и исключения не возникают:

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 Инициализация (стр. 101)
  • Стандарт C11 (ISO/IEC 9899:2011):
  • 6.7.9/11 Инициализация (стр. 140)
  • Стандарт C99 (ISO/IEC 9899:1999):
  • 6.7.8/11 Инициализация (стр. 126)
  • Стандарт C89/C90 (ISO/IEC 9899:1990):
  • 6.5.7 Инициализация