Spec-Zone.ru › C

Постоянные выражения

Несколько разновидностей выражений известны как постоянные выражения

Выражение препроцессора

Выражение, следующее за #if или #elif, должно быть расширено до

  • операторов , кроме присваивания, инкремента, декремента, вызова функции или запятой, аргументы которых являются выражениями препроцессора;
  • целых констант
  • символьных констант
  • специального оператора препроцессора defined

Символьные константы, при вычислении в выражениях #if, могут интерпретироваться в наборе символов исходного файла, наборе символов выполнения или в другом наборе символов, определённом реализацией.

Целочисленная арифметика в выражениях #if выполняется с использованием семантики intmax_t для знаковых типов и uintmax_t для беззнаковых типов.

(с C99)

Целочисленное постоянное выражение

Целочисленное постоянное выражение — это выражение, состоящее только из

  • операторов, кроме присваивания, инкремента, декремента, вызова функции или запятой, за исключением того, что операторы преобразования типов могут преобразовывать только арифметические типы в целочисленные типы, если они не являются частью операнда операторов sizeof, _Alignof(с C11) или typeof/typeof_unqual(с C23).
  • целых констант
  • перечислений
  • символьных констант
  • вещественных констант, но только если они немедленно используются в качестве операндов преобразований в целочисленный тип
  • операторов sizeof над операндами, которые не являются VLA(с C99)
  • операторов _Alignof
(с C11)
  • именованных и составных констант, которые являются целочисленного типа или являются арифметического типа и являются непосредственными операндами преобразований
(с C23)

Целочисленные постоянные выражения вычисляются во время компиляции. Следующие контексты требуют выражений, которые известны как целочисленные постоянные выражения:

  • Размер битового поля.
  • Значение перечисления
  • Метка case оператора switch
  • Размер массива без VLA(с C99)
  • Неявное преобразование целого числа в указатель.
  • Индекс в описателе массива
(с C99)
  • Первый аргумент _Static_assert
  • Целочисленный аргумент _Alignas
(с C11)
  • Количество битов N для битового целого типа (_BitInt(N))
(с C23)

Статическая инициализация

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

1) арифметическим постоянным выражением, которое является выражением любого арифметического типа, состоящим из
  • операторов, кроме присваивания, инкремента, декремента, вызова функции или запятой, за исключением того, что операторы преобразования типов должны преобразовывать арифметические типы в другие арифметические типы, если они не являются частью операнда операторов sizeof, _Alignof(с C11) или typeof/typeof_unqual(с C23)
  • целых констант
  • вещественных констант
  • перечислений
  • символьных констант
  • операторов sizeof над операндами, которые не являются VLA(с C99)
  • операторов _Alignof
(с C11)
  • именованных или составных констант арифметического типа
(с C23)
2) константа нулевого указателя (например, NULL)
3) константа адреса, которая
  • нулевой указатель
  • lvalue обозначающее объект со статической длительностью хранения или указатель на функцию, преобразованный в указатель либо
    • с использованием унарного оператора взятия адреса
    • посредством преобразования целочисленной константы в указатель
    • посредством неявного преобразования массива в указатель или функции в указатель
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:2023):
    • 6.6 Константные выражения (с. TBD)
  • Стандарт C17 (ISO/IEC 9899:2018):
    • 6.6 Константные выражения (с. 76-77)
  • Стандарт C11 (ISO/IEC 9899:2011):
    • 6.6 Константные выражения (с. 106-107)
  • Стандарт C99 (ISO/IEC 9899:1999):
    • 6.6 Константные выражения (с. 95-96)
  • Стандарт C89/C90 (ISO/IEC 9899:1990):
    • 3.4 КОНСТАНТНЫЕ ВЫРАЖЕНИЯ

См. также

Документация C++ по Константным выражениям

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/c/language/constant_expression

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API