读K&R的The C Programmingh Language 2nd,遇到一疑问,书中说:“尽管可以声明enum类型的变量,但编译器不检查这种类型的变量中存储的值是否为该枚举的有效值。不过,枚举变量提供这种检查,因此枚举比#define更具优势。”
枚举变量提供这种检查,什么意思?枚举变量会自己检?当然不是,作者也许想说程序员自己可以写个程序检查付给枚举变量的值是否为该枚举的有效值。
/* 包含头文件 */
#include <stdio.h>
/* 枚举类型 */
enum months{JAN = 1, FEB};
/* 函数原型 */
void enumeration(enum months m);
main()
{
enum months a = 2;
enum months b = 50; /* C中不需要强制转换为enum months类型 */
enum months c = JAN;
enumeration(a);
enumeration(b);
return 0;
}
/* enumeration函数:检测枚举变量存储的值是否为该枚举的有效值 */
void enumeration(enum months m)
{
switch (m)
{
case JAN:
printf("JAN: %d\n", JAN);
break;
case FEB:
printf("FEB: %d\n", FEB);
break;
default:
printf("%d不是该枚举的有效值!\n", m);
break;
}
}
而这段代码如果改为C++源文件编译,却不能通过。原因如下:
根据C标准的规定,枚举常量的类型为int,枚举变量的类型应该与char、有符号或无符号整型兼容。因此,枚举变量可以接受 char、有符号或无符号整型数,而不限于仅从此枚举类型所定义的枚举常量中取值。由于上述原因,在C語言中无法从語法上保证枚举变量只能在定义的枚举成员中取值,只能由程序员自身保证不使用除枚举成员之外的值。
关于這一点,很多介绍C语言的书上或者资料上的描述是不正确的,应该加以注意。
但是,如果给枚举变量赋枚举成员之外的值,有的编译器可能会对此产生警告,有的则不會。因为这种行为不违反C标准的规定,编译器对此如何反应都是有道理的。
然而对于C++来说,编译器会禁止给枚举变量赋予枚举成员之外的值。这是因为C++是一种强类型语言,枚举类型不等同于 int 等其它类型。虽然枚举类型可以隐式转化为 int 等类型,但是 int 等类型却不能自动转化为枚举类型,除非使用强制类型转化。因此,如果不使用强制类型转化的话,给枚举变量赋值则只能从枚举成员中选择。对于枚举类型要避免使用强制类型转换。原因如下:
The C++ Programming Language上说:
如果某个枚举中所有枚举值非负,枚举的表示范围为[0 : 2^k-1];其中2^K是使所有枚举成员位于此范围内的最小的2的幂;如果是负的,就是[-2^k : 2^k-1]。 因此对一个给定的整数值,如果使用强制类型转换,而其值又不在枚举的表示范围以内,其行为是未定义的。
// 包含头文件
#include <iostream.h>
int main()
{
enum months{JAN = 1, FEB, MAR};
//enum months a = 1; //cannot convert from 'const int' to 'enum main::months'
enum months a = (enum months)1;
cout << "a: " << a << endl; //输出: a: 1
enum months b = (enum months)10;
cout << "b: " << b << endl; //输出: b: 10 虽然输出10,但结果是未定义的,因为此枚举的表示范围为:0~3
return 0;
}