Namespaces
Variants

Enumerations

From cppreference.net

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

Содержание

Синтаксис

Перечисляемый тип объявляется с использованием следующего спецификатора перечисления в качестве спецификатора-типа в грамматике объявлений :

enum attr-spec-seq  (необязательно) identifier  (необязательно) { enumerator-list } (1)
enum attr-spec-seq  (необязательно) identifier  (необязательно) : type { enumerator-list } (2) (начиная с C23)
1) Объявляет перечисление без фиксированного базового типа.
2) Объявляет перечисление с фиксированным базовым типом type .

где 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) опциональный список атрибутов ,
  • применяемых ко всему перечислению, если указаны после enum ,
  • применяемых к enumerator , если указаны после enumeration-constant

Как и в случае с 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 массива).

При обработке каждого элемента перечисления в списке перечислителей тип элемента перечисления должен быть:

  • ранее объявленный тип, если это повторное объявление того же элемента перечисления; или,
  • тип перечисления, для перечисления с фиксированным базовым типом; или,
  • int , если в списке перечислителей нет предыдущих элементов перечисления и нет явного = с определяющим целочисленным константным выражением; или,
  • int , если задан явно с = и значение целочисленного константного выражения представимо типом int; или,
  • тип целочисленного константного выражения, если задан явно с = и если значение целочисленного константного выражения не представимо типом int ; или,
  • тип значения последнего элемента перечисления с добавлением 1. Если такое целочисленное константное выражение приведет к переполнению или циклическому переносу значения предыдущего элемента перечисления при добавлении 1, тип принимает либо:
    • подходящий знаковый целочисленный тип (исключая битово-точные знаковые целочисленные типы), способный представить значение предыдущего элемента перечисления плюс 1; или,
    • подходящий беззнаковый целочисленный тип (исключая битово-точные беззнаковые целочисленные типы), способный представить значение предыдущего элемента перечисления плюс 1.

Знаковый целочисленный тип выбирается, если предыдущий элемент перечисления, к которому добавляется значение, имеет знаковый целочисленный тип. Беззнаковый целочисленный тип выбирается, если предыдущий элемент перечисления имеет беззнаковый целочисленный тип. Если нет подходящего целочисленного типа из описанных ранее, который может представить новое значение, то перечисление не имеет типа, способного представить все его значения.

(since C23)
enum color { RED, GREEN, BLUE } r = RED;
switch(r)
{
case RED:
    puts("красный");
    break;
case GREEN:
    puts("зелёный");
    break;
case BLUE:
    puts("синий");
    break;
}

Если 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)

Тип элемента перечисления для типа перечисления без фиксированного базового типа после завершения:

  • int если все значения перечисления представимы как int ; или,
  • тип перечисления.
(начиная с 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
}

Пример

#include <stdio.h>
int main(void)
{
    enum TV { FOX = 11, CNN = 25, ESPN = 15, HBO = 22, MAX = 30, NBC = 32 };
    printf("List of cable stations:\n");
    printf(" FOX: \t%2d\n", FOX);
    printf(" HBO: \t%2d\n", HBO);
    printf(" MAX: \t%2d\n", MAX);
}

Вывод:

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 Спецификаторы перечисления

Ключевые слова

enum

Смотрите также

Документация C++ для объявления перечисления