Constant expressions
Несколько видов выражений известны как constant expressions .
Содержание |
Препроцессорное константное выражение
Выражение, следующее за
#if
или
#elif
должно раскрываться в
- операторы кроме присваивания , инкремента, декремента , вызова функции , или запятой , аргументы которых являются препроцессорными константными выражениями
- целочисленные константы
- символьные константы
-
специальный препроцессорный оператор
defined.
Символьные константы, когда вычисляются в
#if
-выражениях, могут интерпретироваться в исходной
символьной кодировке, исполнительной символьной кодировке или в некоторой другой определяемой реализацией символьной кодировке.
|
Целочисленная арифметика в
|
(since C99) |
Целочисленное константное выражение
Целочисленное константное выражение — это выражение, которое состоит только из
- операторы , кроме присваивания , инкремента, декремента , вызова функции , или запятой , за исключением того, что операторы приведения могут приводить арифметические типы только к целочисленным типам, если они не являются частью операнда для sizeof , _Alignof (начиная с C11) (до C23) , alignas (начиная с C23) или typeof/typeof_unqual (начиная с C23) .
- целочисленные константы
- константы перечисления
- символьные константы
- вещественные константы , но только если они непосредственно используются как операнды приведений к целочисленному типу
-
sizeofоператоры , операнды которых не являются VLA (начиная с C99)
|
(начиная с C11) |
|
(since C23) |
Целочисленные константные выражения вычисляются во время компиляции. Следующие контексты требуют выражений, известных как целочисленные константные выражения :
- Размер битового поля .
- Значение перечислимой константы
-
Метка
caseоператора switch - Размер массива не-VLA (начиная с C99)
- Неявное преобразование целого числа в указатель.
|
(начиная с C99) |
|
(начиная с C11) |
|
(начиная с C23) |
Статический инициализатор
Выражения, которые используются в инициализаторах объектов со статической и thread_local продолжительностью хранения или объявленных с описателем класса хранения constexpr (since C23) должны быть либо строковыми литералами, либо выражениями, которые могут быть одним из следующих
-
- операторов , кроме присваивания , инкремента, декремента , вызова функции , или запятой , за исключением того, что операторы приведения должны преобразовывать арифметические типы в другие арифметические типы, если они не являются частью операнда для sizeof , _Alignof (since C11) (until C23) , alignof (since C23) или typeof/typeof_unqual (since C23) оператора
- целочисленных констант
- вещественных констант
- констант перечисления
- символьных констант
-
sizeofоператоров , операнды которых не являются VLA (since C99)
| (since C11) |
|
(since C23) |
-
- нулевым указателем
- lvalue , обозначающим объект со статической storage duration , или обозначением функции, преобразованным в указатель либо
-
- с использованием унарного оператора взятия адреса
- приведением целочисленной константы к указателю
- неявным conversion массива к указателю или функции к указателю.
|
5)
именованная константа
, то есть идентификатор, который является
.
к именованной константе структурного или объединённого типа, даже рекурсивно.
6)
константа составного литерала
, которая является
Константа структуры или объединения
- это соответственно именованная константа или константа составного литерала с типом структуры или объединения. Если оператор доступа к члену
|
(since C23) |
В отличие от целочисленных константных выражений, статические инициализирующие выражения не обязаны вычисляться на этапе компиляции; компилятор имеет право преобразовать такие инициализаторы в исполняемый код, который вызывается до запуска программы.
static int i = 2 || 1 / 0; // инициализирует i значением 1
|
Этот раздел не завершён
Причина: другие мини-примеры |
Значение статического инициализатора с плавающей точкой никогда не бывает менее точным, чем значение того же выражения, выполняемого во время выполнения, но может быть более точным.
Выражения с плавающей точкой констант
Арифметические константные выражения типов с плавающей точкой, которые не используются в статических инициализаторах, всегда вычисляются как-будто во время выполнения и подвержены влиянию текущего округления (если FENV_ACCESS включен) и сообщают об ошибках в соответствии с 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.
Ссылки
- Стандарт C23 (ISO/IEC 9899:2024):
-
- 6.6 Константные выражения (стр: 95-96)
- Стандарт 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 CONSTANT EXPRESSIONS
Смотрите также
|
Документация C++
для
Константных выражений
|