enumC 还为我们提供了另一种用名字表示整数常量的方式:enum。
例如:
enum {
ONE=1,
TWO=2
};
printf("%d %d", ONE, TWO); // 1 2在某些方面,它可能比使用 #define 更好——或者只是有所不同。主要区别如下:
enum 只能是整型。#define 可以定义任何东西。enum 常常按其符号标识符名显示。#define 定义的数字只显示为原始数值,调试时更难弄清它的含义。由于它们属于整数类型,所以凡是整数能用的地方它们都能用,包括数组维度和 case 语句。
我们再来深入剖析一下。
enum 的行为除非你手动改写,否则 enum 会自动编号。
默认情况下,它们从 0 开始,并由此自动递增:
enum {
SHEEP, // 值为 0
WHEAT, // 值为 1
WOOD, // 值为 2
BRICK, // 值为 3
ORE // 值为 4
};
printf("%d %d\n", SHEEP, BRICK); // 0 3也可以强制指定特定的整数值,就像前面看到的那样:
enum {
X=2,
Y=18,
Z=-2
};值重复也没问题:
enum {
X=2,
Y=2,
Z=2
};如果省略了值,编号就会从最后指定的那个值开始,沿正方向继续计数。例如:
enum {
A, // 0,默认起始值
B, // 1
C=4, // 4,手动设置
D, // 5
E, // 6
F=3, // 3,手动设置
G, // 4
H // 5
}如果你喜欢这种风格,这样写完全没问题:
enum {
X=2,
Y=18,
Z=-2, // <-- 尾随逗号
};近几十年来的语言里,这种写法越来越流行,所以看到它你也许会高兴。
enum 的作用域符合你的预期:如果在文件作用域,整个文件都能看到它;如果在某个块内,它就是该块的局部。
把 enum 定义在头文件里非常常见,这样就可以在文件作用域中 #include 它。
你可能已经注意到,习惯上会把 enum 的符号声明为大写(用下划线分隔)。
这并不是硬性要求,但确实是非常非常常见的惯用法。
enum 是一种类型关于 enum,有一点很重要:它是一种类型,就跟 struct 是一种类型一样。
你可以给它一个标签名,以便之后引用这个类型并声明该类型的变量。
既然 enum 是整数类型,那为什么不干脆用 int 呢?
在 C 中,最好的理由是代码清晰——它是一种漂亮、带类型的方式,能在代码中表达你的想法。C(与 C++ 不同)实际上并不强制某个 enum 的取值落在任何范围内。
我们来看一个例子,其中声明一个类型为 enum resource 的变量 r,它可以存放这些值:
// 具名枚举,类型为 "enum resource"
enum resource {
SHEEP,
WHEAT,
WOOD,
BRICK,
ORE
};
// 声明一个类型为 "enum resource" 的变量 "r"
enum resource r = BRICK;
if (r == BRICK) {
printf("I'll trade you a brick for two sheep.\n");
}当然,你也可以给它们加上 typedef,不过我个人不喜欢这么做。
typedef enum {
SHEEP,
WHEAT,
WOOD,
BRICK,
ORE
} RESOURCE;
RESOURCE r = BRICK;另一种合法但少见的捷径,是在声明 enum 的同时声明变量:
// 声明一个枚举,以及几个该类型的已初始化变量:
enum {
SHEEP,
WHEAT,
WOOD,
BRICK,
ORE
} r = BRICK, s = WOOD;你也可以给 enum 起个名字,以便之后使用,这多半就是你在大多数情况下想做的事:
// 声明一个枚举,以及几个该类型的已初始化变量:
enum resource { // <-- 类型现在为 "enum resource"
SHEEP,
WHEAT,
WOOD,
BRICK,
ORE
} r = BRICK, s = WOOD;简而言之,enum 是写出漂亮、作用域清晰、带类型、整洁的代码的好办法。