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 是一个逗号分隔的列表 (允许尾随逗号) (since C99) ,每个元素的形式为:

枚举常量 属性说明符序列  (可选) (1)
枚举常量 属性说明符序列  (可选) = 常量表达式 (2)

其中

identifier , enumeration-constant - 通过此声明引入的标识符
constant-expression - 整型常量表达式 其值可表示为 int 类型的值 (C23前) 若枚举具有固定底层类型,其值可表示为 type 类型的值 (C23起)
attr-spec-seq - (C23) 可选的 属性 列表,
  • 若出现在 enum 之后,则应用于整个枚举
  • 若出现在 enumeration-constant 之后,则应用于该 enumerator

struct union 类似,引入枚举类型及一个或多个枚举常量的声明,也可以声明该类型或派生自该类型的一个或多个对象。

enum color { RED, GREEN, BLUE } c = RED, *cp = &c;
// 引入枚举类型 enum color
// 整型常量 RED, GREEN, BLUE
// 类型为 enum color 的对象 c
// 类型为指向 enum color 指针的对象 cp

说明

每个出现在枚举说明符主体中的 枚举常量 都会成为封闭作用域中的 整数常量 其类型为 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("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

如果使用了 identifier 本身,它将成为 命名空间 标签中枚举类型的名称,并要求使用enum关键字(除非通过typedef将其引入普通命名空间)。

enum color { RED, GREEN, BLUE };
enum color r = RED; // 正确
// color x = GREEN; // 错误:color不在普通命名空间中
typedef enum color color_t;
color_t x = GREEN; // 正确

每个 无固定底层类型的 (C23起) 枚举类型都与以下类型之一 兼容 char 、有符号整数类型或无符号整数类型 (不包括 bool 和位精确整数类型) (C23起) 。具体哪种类型与给定枚举类型兼容由实现定义,但无论选择何种类型,都必须能够表示该枚举的所有枚举值。 对于所有具有固定底层类型的枚举,其枚举类型与枚举的底层类型兼容。 (C23起)

对于无固定底层类型的枚举类型,其枚举成员类型在定义完成时为:

  • 若枚举的所有值均可表示为 int 类型,则为 int ;或
  • 该枚举类型本身
(since C23)
所有枚举类型均具有底层类型。可通过枚举类型说明符显式指定底层类型,此时该类型即为固定底层类型。若未显式指定,则底层类型为该枚举的兼容类型——可能是有符号或无符号整数类型,或 char 类型。 (since C23)

枚举类型是整数类型,因此可以用于其他整数类型适用的任何场景,包括 隐式转换 算术运算符

enum { ONE = 1, TWO } e;
long n = ONE; // 整型提升
double d = ONE; // 类型转换
e = 1.2; // 类型转换,e 当前值为 ONE
e = e + 1; // e 当前值为 TWO

注释

结构体 联合体 不同,C语言中不存在前向声明枚举:

enum Color; // 错误:C语言中枚举不支持前向声明
enum Color { RED, GREEN, BLUE };

枚举允许以比 #define 更便捷和结构化的方式声明命名常量;它们在调试器中可见,遵循作用域规则,并参与类型系统。

#define TEN 10
struct S { int x : TEN; }; // 正确

enum { TEN = 10 };
struct S { int x : TEN; }; // 同样有效

自 C23 起, constexpr 可用于实现相同目的:

constexpr int TEN = 10;
struct S { int x : TEN; }; // 同样有效

此外,由于 结构体 联合体 在C语言中不会建立独立作用域,枚举类型及其枚举常量可以在结构体/联合体的成员声明中定义,且其作用域与所属结构体/联合体相同。

struct Element
{
    int z;
    enum State { SOLID, LIQUID, GAS, PLASMA } state;
} oxygen = { 8, GAS };
// 枚举类型 State 及其枚举常量在此处保持可见,例如:
void foo(void)
{
    enum State e = LIQUID; // 正确
    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 类型 (p: 39)
  • 6.7.2.2 枚举说明符 (p: 107-112)
  • C17 标准 (ISO/IEC 9899:2018):
  • 6.2.5/16 类型 (p: 32)
  • 6.7.2.2 枚举说明符 (p: 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++ 文档 关于 枚举声明