想让代码里出现写代码的人看得懂的名字而不是一串魔法数字,用枚举(enum)。它给一组整数常量起上容易理解的名字,状态、错误码、菜单选项这类场景特别合适。

最简单的枚举

第一步:先体会没有枚举的痛。想表达一个计算器支持加/减/乘/除,只能这样:

int op = 2;   /* 2 是啥?没人知道 */

枚举把它变成名字:

enum calculate { SUM, DIFFERENCE, PRODUCT, QUOTIENT };

默认情况下,SUM 自动是 0、DIFFERENCE 是 1、PRODUCT 是 2、QUOTIENT 是 3,依次加 1。用起来:

C 语言枚举示例运行
#include <stdio.h>

enum direction { EAST, NORTH, WEST, SOUTH };

int main() {
    enum direction dir = NORTH;   /* dir 存的是 1 */
    printf("%d\n", dir);          // 1

    dir = 3;   /* 直接赋整数值也行 */
    printf("%d\n", dir);          // 3
    return 0;
}

名字按标准命名规则来,惯例用全大写,一眼分清这是在引用常量。同一作用域里枚举常量名要唯一,两个枚举都定义 PRODUCT 会编译报错。

手动指定值

默认从 0 开始太死板,可以手动指定,没指定的自动顺着上一个加:

enum enm { a = 3, b = 2, c };   /* c 自动是 3(b 的值 2 加 1) */

enum enm v1 = a, v2 = b, v3 = c;
printf("%d %d %d\n", v1, v2, v3);   // 3 2 3

值可以乱序,但必须是整数。不过直接用裸数字就丢了枚举起名的意义,用名字比用裸数字更清晰。

大小与内存

枚举定义本身不占内存,占内存的是枚举变量。大多数编译器把它实现成 int,大小和 int 一样,可以用 sizeof 验证:

printf("%zu bytes\n", sizeof(dir));   // 4 bytes(通常)

个别编译器会挑更小的类型来装,不必纠结,直接认为"约等于 int"即可。

typedef 让枚举更顺手

enum direction 长,用 typedef 起个短名:

typedef enum direction {
    EAST, NORTH, WEST, SOUTH
} Dirctn;

Dirctn dir = NORTH;   /* 不用再写 enum 关键字 */

枚举的好用之处

  • 状态机:游戏角色、进程控制的各个状态。
  • 错误码:给整组错误码起名,出错时看名字就知道哪挂了。
  • 菜单/用户输入:星期几、选项几,命名比数字直观。
  • 文件权限:READ、WRITE、EXECUTE。

能用名字就别用魔法数字,可读性马上上一个台阶。