枚举
1. 定义
- 枚举由一组已命名的整数常量值组成,每个不同的枚举构成不同的枚举类型
- 每个枚举都有一个底层类型
2. 声明
枚举类型的声明为:enum (属性声明符序列) (标识符) (: 类型) { 枚举项列表 }
- 枚举项列表中的每个
枚举项之间由逗号分隔 - 每个
枚举项为枚举常量 (= 常量表达式)的形式 - 如果省略
: 类型,则为无固定底层类型的枚举:这个枚举的底层类型由实现定义,这个类型一定能表示每一个枚举项的值; 否则为固定底层类型的的枚举,底层类型即为类型
当某个枚举项省略 = 常量表达式 时,它的值等于前一项加一;首项若也省略,则默认从 0 开始。
c
enum color {
COLOR_RED, // 0
COLOR_GREEN, // 1
COLOR_BLUE = 8, // 8
COLOR_ALPHA // 9
};1
2
3
4
5
6
2
3
4
5
6
运行结果:该代码块主要用于语法或结构说明,单独运行通常无终端输出。
3. 作用域与名称
枚举常量名进入其所在作用域,不带 enum 前缀,因此要避免与其他标识符重名。枚举类型名本身需要通过 enum 类型名 使用;如果希望省去 enum 关键字,可以配合 typedef。
c
typedef enum color color_t;
color_t c = COLOR_GREEN;1
2
3
2
3
运行结果:该代码块主要用于语法或结构说明,单独运行通常无终端输出。
4. 转换与比较
枚举对象在表达式中会参与整数转换规则。比较和 switch 分支通常都可直接使用枚举常量,这比散落的整数字面量更清晰。
c
enum state {
STATE_INIT,
STATE_READY,
STATE_STOP
};
int run(enum state s) {
switch (s) {
case STATE_INIT:
return 0;
case STATE_READY:
return 1;
case STATE_STOP:
return 2;
}
return -1;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
运行结果:该代码块主要用于语法或结构说明,单独运行通常无终端输出。
switch 默认分支仍然建议保留,因为枚举对象在运行期仍可能接收到未预期值。
5. 关于固定底层类型
固定底层类型写法(enum E : unsigned char)属于 C23 能力;如果目标编译器尚未支持 C23,可继续使用普通枚举并在接口边界处做范围约束。
6. 重复枚举值是合法的
枚举常量值可以重复,标准并不禁止。这个特性可用于“别名常量”或兼容旧命名,但要注意可读性:如果多个名字映射到同一数值,switch 分支应明确注释意图,避免阅读时误以为遗漏分支。
c
enum token_kind {
TOK_EOF = 0,
TOK_END = 0, /* 与 TOK_EOF 同值,作为兼容别名 */
TOK_ID = 1
};1
2
3
4
5
2
3
4
5
运行结果:该代码块主要用于语法或结构说明,单独运行通常无终端输出。
7. 枚举与位标志不是同一模型
普通枚举更适合“互斥状态”,例如解析器阶段、连接状态、错误类别;位标志更适合“可组合选项”。如果把可组合标志硬塞进普通状态枚举,分支会迅速膨胀。需要组合语义时,通常应改用无符号整数掩码并单独定义位常量。