Перечисления
Тип перечисления — это отдельный тип, значение которого является значением его основного типа (см. ниже), включающего значения явно указанных констант (констант перечисления).
Синтаксис
Тип перечисления объявляется с помощью следующего спецификатора перечисления в качестве спецификатора типа в грамматике объявления:
enum attr-spec-seq (необязательно) идентификатор (необязательно) { список_перечислителей } | (1) | |
enum attr-spec-seq (необязательно) идентификатор (необязательно) : тип { список_перечислителей } | (2) | (с C23) |
где список_перечислителей — это список перечислителей, разделённых запятыми(с разрешенной запятой в конце)(с C99), каждый из которых имеет вид:
| константа_перечисления attr-spec-seq (необязательно) | (1) | |
константа_перечисления attr-spec-seq (необязательно) = выражение_константы | (2) |
где
| идентификатор, константа_перечисления | - | идентификаторы, введенные этим объявлением |
| выражение_константы | - | целочисленное выражение-константа значение которого представимо как значение типа int(до C23). Если перечисление имеет фиксированный базовый тип, представимый как значение тип(с C23) |
| attr-spec-seq | - | (C23)необязательный список атрибутов,
|
Как и в случае с struct или union, объявление, которое ввело тип перечисления и одну или несколько констант перечисления, может также объявить одну или несколько переменных этого типа или производного от него типа.
enum color { RED, GREEN, BLUE } c = RED, *cp = &c;
// introduces the type enum color
// the integer constants RED, GREEN, BLUE
// the object c of type enum color
// the object cp of type pointer to enum colorОбъяснение
Каждая константа_перечисления, которая появляется в теле спецификатора перечисления, становится целочисленной константой типа int(до C23) в охватывающей области видимости и может быть использована, где требуются целочисленные константы (например, как метка case или как размер массива без VLA).
| Во время обработки каждой константы перечисления в списке перечислителей, тип константы перечисления должен быть:
Знаковый целочисленный тип выбирается, если предыдущая константа перечисления, к которой добавляется, является знаковым целочисленным типом. Беззнаковый целочисленный тип выбирается, если предыдущая константа перечисления является беззнаковым целочисленным типом. Если нет подходящего по размеру целочисленного типа, описанного ранее, который может представить новое значение, то у перечисления нет типа, способного представить все его значения. | (с C23) |
enum color { RED, GREEN, BLUE } r = RED;
switch(r)
{
case RED:
puts("red");
break;
case GREEN:
puts("green");
break;
case BLUE:
puts("blue");
break;
}Если константа_перечисления следует за = выражение_константы, её значение равно значению этого выражения-константы. Если константа_перечисления не следует за = выражение_константы, её значение на единицу больше значения предыдущего перечислителя в том же перечислении. Значение первого перечислителя (если он не использует = выражение_константы) равно нулю.
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Сам идентификатор, если используется, становится именем типа перечисления в пространстве имён пространстве имён и требует использования ключевого слова enum (если не переопределён с помощью typedef в обычное пространство имён).
enum color { RED, GREEN, BLUE };
enum color r = RED; // OK
// color x = GREEN: // Error: color is not in ordinary name space
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; // promotion
double d = ONE; // conversion
e = 1.2; // conversion, e is now ONE
e = e + 1; // e is now TWOПримечания
В отличие от struct или union, в C нет перечислений с предварительной декларацией:
enum Color; // Error: no forward-declarations for enums in C
enum Color { RED, GREEN, BLUE };Перечисления позволяют объявить именованные константы более удобным и структурированным способом, чем #define; они видны в отладчике, подчиняются правилам области видимости и участвуют в системе типов.
#define TEN 10
struct S { int x : TEN; }; // OKили
enum { TEN = 10 };
struct S { int x : TEN; }; // also OKС C23 constexpr можно использовать для той же цели:
constexpr int TEN = 10;
struct S { int x : TEN; }; // also OKКроме того, поскольку struct или union не устанавливают свою область видимости в C, тип перечисления и его константы перечисления могут быть введены в спецификацию члена первого, и их область видимости будет такой же, как и у первого, после этого.
struct Element
{
int z;
enum State { SOLID, LIQUID, GAS, PLASMA } state;
} oxygen = { 8, GAS };
// type enum State and its enumeration constants stay visible here, e.g.
void foo(void)
{
enum State e = LIQUID; // OK
printf("%d %d %d ", e, oxygen.state, PLASMA); // prints 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:2023):
- 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++ по объявлению перечислений |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/c/language/enum