经常需要为某些属性定义一组可选择的值。例如,文件打开的状态可能会有三种:输入、输出和追加。记录这些状态值的一种方法是使每种状态都与一个唯一的常数值相关联。我们可能会这样编写代码:
const int input = 0;
const int output = 1;
const int append = 2;
虽然这种方法也能奏效,但是它有个明显的缺点:没有指出这些值是相关联的 。 枚举 ( enumeration )提供了一种替代的方法,不但定义了整数常量集,而且还把它们进行了分组。
1. 定义和初始化枚举
枚举的定义包括关键字 enum ,其后是一个可选的枚举类型名,和一个用花括号括起来、用逗号分开的 枚举成员 ( enumerators ) 列表。
// input is 0, output is 1, and append is 2
enum open_modes {input, output, append};
默认地,第一个枚举成员赋值为0,后面的每个枚举成员赋的值比前面的大 1 。
2. 枚举成员是常量
可以为一个或多个枚举成员提供初始值,用来初始化枚举成员的值必须是一个 常量表达式 ( constant expression ) 。常量表达式是编译器在编译时就能够计算出结果的整型表达式。整型字面值常量是常量表达式,正如一个通过常量表达式自我初始化的 const 对象( 2.4 节)也是常量表达式一样。
例如,可以定义下列枚举类型:
// shape is 1, sphere is 2, cylinder is 3, polygon is 4
enum Forms {shape = 1, sphere, cylinder, polygon};
在枚举类型 Forms 中,显式将 shape 赋值为 1 。其他枚举成员隐式初始化: sphere 初始化为 2 , cylinder 初始化为 3 , polygon 初始化为 4 。
枚举成员值可以是不唯一的。
// point2d is 2, point2w is 3, point3d is 3, point3w is 4
enum Points { point2d = 2, point2w,
point3d = 3, point3w };
本例中,枚举成员 point2d 显式初始化为 2 。下一个枚举成员 point2w 默认初始化,即它的值比前一枚举成员的值大 1 。因此 point2w 初始化为 3 。枚举成员 point3d 显式初始化为 3 。一样, point3w 默认初始化,结果为 4 。
不能改变枚举成员的值。枚举成员本身就是一个常量表达式,所以也可用于需要常量表达式的任何地方 。
3. 每个enum 都定义一种唯一的类型
每个 enum 都定义了一种新的类型。和其他类型一样,可以定义和初始化 Points 类型的对象,也可以以不同的方式使用这些对象。枚举类型的对象的初始化或赋值,只能通过其枚举成员或同一枚举类型的其他对象来进行:
Points pt3d = point3d; // ok: point3d is a Points enumerator
Points pt2w = 3; // error: pt2w initialized with int
pt2w = polygon; // error: polygon is not a Points enumerator
pt2w = pt3d; // ok: both are objects of Points enum type
注意把 3 赋给 Points 对象是非法的,即使 3 与一个 Points 枚举成员相关联。
宏和枚举的区别(#define VS enum)
宏和枚举之间的差别主要在作用的时期和存储的形式不同,宏是在预处理的阶段进行替换工作的,它替换代码段的文本,程序运行的过程中宏已不存在了。而枚举是在程序运行之后才起作用的, 枚举常量存储在数据段的静态存储区里 。宏占用代码段的空间,而枚举除了占用空间,还消耗CPU资源。
但也不能就此说宏比枚举好,如果需要定义非常多的常量,用一条enum {.....}明显比一大堆define更清晰,枚举也可以用来定义一些特殊类型,比如Bool,如:
type enum {FALSE,TRUE} Bool;