Enumerations
Перечисляемый тип — это отдельный тип , значение которого является значением его базового типа (см. ниже), включая значения явно именованных констант ( констант перечисления ).
Содержание |
Синтаксис
Перечисляемый тип объявляется с использованием следующего спецификатора перечисления в качестве спецификатора-типа в грамматике объявлений :
enum
attr-spec-seq
(необязательно)
identifier
(необязательно)
{
enumerator-list
}
|
(1) | ||||||||
enum
attr-spec-seq
(необязательно)
identifier
(необязательно)
:
type
{
enumerator-list
}
|
(2) | (начиная с C23) | |||||||
где enumerator-list представляет собой разделённый запятыми список (с разрешённой завершающей запятой) (начиная с C99) из enumerator , каждый из которых имеет вид:
| enumeration-constant attr-spec-seq (необязательно) | (1) | ||||||||
enumeration-constant
attr-spec-seq
(необязательно)
=
constant-expression
|
(2) | ||||||||
где
| identifier , enumeration-constant | - | идентификаторы, вводимые этим объявлением |
| constant-expression | - | целочисленное константное выражение , значение которого представимо в виде значения типа int (до C23) . Если перечисление имеет фиксированный базовый тип, представимо в виде значения type (начиная с C23) |
| attr-spec-seq | - |
(C23)
опциональный список
атрибутов
,
|
Как и в случае с struct или union , объявление, которое вводит перечисляемый тип и одну или несколько констант перечисления, может также объявлять один или несколько объектов этого типа или типа, производного от него.
enum color { RED, GREEN, BLUE } c = RED, *cp = &c; // вводит тип enum color // целочисленные константы RED, GREEN, BLUE // объект c типа enum color // объект cp типа pointer to enum color
Объяснение
Каждый enumeration-constant , который появляется в теле спецификатора перечисления, становится целочисленной константой с типом int (до C23) в охватывающей области видимости и может использоваться везде, где требуются целочисленные константы (например, в качестве метки case или в качестве размера не-VLA массива).
|
При обработке каждого элемента перечисления в списке перечислителей тип элемента перечисления должен быть:
Знаковый целочисленный тип выбирается, если предыдущий элемент перечисления, к которому добавляется значение, имеет знаковый целочисленный тип. Беззнаковый целочисленный тип выбирается, если предыдущий элемент перечисления имеет беззнаковый целочисленный тип. Если нет подходящего целочисленного типа из описанных ранее, который может представить новое значение, то перечисление не имеет типа, способного представить все его значения. |
(since C23) |
Если enumeration-constant сопровождается = constant-expression , его значение равно значению этого константного выражения. Если enumeration-constant не сопровождается = constant-expression , его значение на единицу больше значения предыдущего перечислителя в том же перечислении. Значение первого перечислителя (если он не использует = constant-expression ) равно нулю.
enum Foo { A, B, C = 10, D, E = 1, F, G = F + C }; // A=0, B=1, C=10, D=11, E=1, F=2, G=12
Сам идентификатор , если используется, становится именем типа перечисления в пространстве имён name space и требует использования ключевого слова enum (если не переопределён через typedef в обычное пространство имён).
enum color { RED, GREEN, BLUE }; enum color r = RED; // OK // color x = GREEN; // Ошибка: color не находится в обычном пространстве имен typedef enum color color_t; color_t x = GREEN; // OK
Каждый перечислимый тип без фиксированного базового типа (начиная с C23) является совместимым с одним из: char , знаковым целочисленным типом или беззнаковым целочисленным типом (исключая bool и битово-точные целочисленные типы) (начиная с C23) . Определяется реализацией, с каким типом совместим любой заданный перечислимый тип, но каким бы он ни был, он должен быть способен представлять все значения перечислителей этого перечисления. Для всех перечислений с фиксированным базовым типом, перечислимый тип совместим с базовым типом перечисления. (начиная с C23)
|
Тип элемента перечисления для типа перечисления без фиксированного базового типа после завершения:
|
(начиная с C23) |
| Все перечисления имеют базовый тип. Базовый тип может быть явно указан с использованием спецификатора типа перечисления и является его фиксированным базовым типом. Если он не указан явно, базовый тип является совместимым типом перечисления, который представляет собой знаковый или беззнаковый целочисленный тип, или char . | (начиная с C23) |
Перечисляемые типы являются целочисленными типами и, как таковые, могут использоваться везде, где могут использоваться другие целочисленные типы, включая неявные преобразования и арифметические операторы .
enum { ONE = 1, TWO } e; long n = ONE; // приведение double d = ONE; // преобразование e = 1.2; // преобразование, e теперь ONE e = e + 1; // e теперь TWO
Примечания
В отличие от struct или union , в C не существует предварительно объявленных перечислений:
enum Color; // Ошибка: в C нет предварительных объявлений для перечислений enum Color { RED, GREEN, BLUE };
Перечисления позволяют объявлять именованные константы более удобным и структурированным способом, чем #define ; они видны в отладчике, подчиняются правилам области видимости и участвуют в системе типов.
#define TEN 10 struct S { int x : TEN; }; // OK
или
enum { TEN = 10 }; struct S { int x : TEN; }; // также корректно
Начиная с C23 constexpr может использоваться для той же цели:
constexpr int TEN = 10; struct S { int x : TEN; }; // также корректно
Кроме того, поскольку struct или union не устанавливают свою область видимости в C, тип перечисления и его константы могут быть объявлены в спецификации членов структуры или объединения, и их область видимости будет совпадать с областью видимости структуры или объединения.
struct Element { int z; enum State { SOLID, LIQUID, GAS, PLASMA } state; } oxygen = { 8, GAS }; // тип enum State и его константы перечисления остаются видимыми здесь, например void foo(void) { enum State e = LIQUID; // OK printf("%d %d %d ", e, oxygen.state, PLASMA); // выводит 1 2 3 }
Пример
Вывод:
List of cable stations: FOX: 11 HBO: 22 MAX: 30
Ссылки
- Стандарт C23 (ISO/IEC 9899:2024):
-
- 6.2.5/21 Типы (стр: 39)
-
- 6.7.2.2 Спецификаторы перечисления (стр: 107-112)
- Стандарт C17 (ISO/IEC 9899:2018):
-
- 6.2.5/16 Типы (стр: 32)
-
- 6.7.2.2 Спецификаторы перечисления (стр: 84-85)
- Стандарт C11 (ISO/IEC 9899:2011):
-
- 6.2.5/16 Типы (стр: 41)
-
- 6.7.2.2 Спецификаторы перечисления (стр: 117-118)
- Стандарт C99 (ISO/IEC 9899:1999):
-
- 6.2.5/16 Типы (стр: 35)
-
- 6.7.2.2 Спецификаторы перечисления (стр: 105-106)
- Стандарт C89/C90 (ISO/IEC 9899:1990):
-
- 3.1.2.5 Типы
-
- 3.5.2.2 Спецификаторы перечисления
Ключевые слова
Смотрите также
|
Документация C++
для
объявления перечисления
|