C/C++的enum类型大小
我们在编程时有时想让一个变量的值只在规定范围里取值,那么就会考虑使用enum类型。
例如我们想定义一个变量来表示红绿蓝三原颜色,那么就使用enum来定义取值范围,
enum color {RED, GREEN, BLUE};
然后我们在用enum color来定义变量,并赋值,
enum color myColor = GREEN;
本文不是讨论enum的使用细节,而是看一下enum类型的变量大小。
一 C下的enum
C语言下面,enum大小是一个整型大小,但是C下整型有很多种,char、long int和short int等,具体哪一种呢?下面引用《C in a nutshell》里的一句话来解释下,
The compiler may select the appropriate integer type depending on the defined values of
the enumeration constants.
意思就是enum类型的大小是由编译器根据定义值的大小来选择合适的整数类型,所以enum类型的大小并不是固定的。
下面这个代码例子可以说明这个问题,
#include <stdio.h>
enum color1
{
RED = 0,
GREEN,
BLUE
};
enum color2
{
GRAY = 0x1122334455,
YELLOW,
PURPLE
};
int main(void)
{
printf("enum color1: %d\n", sizeof(enum color1));
printf("enum color2: %d\n", sizeof(enum color2));
return 0;
}
输出如下,
因为enum color2的大小已经超过了4个字节,这样编译器就会把它的大小扩大。
这样会有一个潜在的弊端:如果我们定义了一个结构体,其成员有enum类型,那么就可能导致结构体大小发生变化,而我们却没有察觉,例如随着代码的更迭,我们加入了更多enum规定的范围值,当超过某个值时,它的大小就产生了变化,这是比较危险的。
二 C++11下的enum
C++11下,enum类型可以显式的指定大小,
#include <cstdio>
#include <cstdint>
enum color1 : uint8_t
{
RED,
GREEN,
BLUE
};
enum color2 : uint16_t
{
GRAY,
YELLOW,
PURPLE
};
int main(void)
{
printf("enum color1: %d\n", sizeof(enum color1));
printf("enum color2: %d\n", sizeof(enum color2));
return 0;
}
输出如下,
因为显式的指定了enum color1为一个字节大小,enum color2为2个字节大小。而且如果enum规定的范围值超过了指定大小,编译会报错,如这种,
enum color1 : uint8_t
{
RED = 266,
GREEN,
BLUE
};
出错信息如下,
三 C和C++11的enum使用区别
1. enum关键字
在C下我们使用enum去定义变量时必须带上enum这个关键字,而在C++11下可以不用带这个关键字,更加人性化了一点,如下
// c++11 code
#include <cstdio>
#include <cstdint>
enum color
{
RED,
GREEN,
BLUE
};
int main(void)
{
printf("enum color1: %d\n", sizeof(color));
color myColor = GREEN;
return 0;
}
2. enum变量的取值范围
这是很重要的一点区别:在C下enum定义的变量可以赋规定范围外的值,而在C++11下这是不允许的。
下面是C代码,
// c code
#include <stdio.h>
enum color
{
RED = 0,
GREEN,
BLUE
};
int main(void)
{
enum color myColor;
myColor = GREEN;
printf("myColor: %d\n", myColor);
myColor = 10;
printf("myColor: %d\n", myColor);
return 0;
}
输出如下,
个人感觉这是不好的,因为我们已经规定了范围,但是现在整个变量却可以赋一个范围外的值。
而在C++11里,这样写编译就不通过,
// c++11 code
#include <cstdio>
#include <cstdint>
enum color : uint8_t
{
RED,
GREEN,
BLUE
};
int main(void)
{
color myColor;
myColor = GREEN; // correct
printf("myColor: %d\n", myColor);
myColor = 10; // error
printf("myColor: %d\n", myColor);
myColor = 1; // error
printf("myColor: %d\n", myColor);
return 0;
}
可以看到C++11下enum的值必须从规定范围里取,即使是对应的数字也不行,这样就把enum类型的变量值实实在在的限制在规定范围里了,就不用担心会出现范围外的值。
关于C++11的enum,还有很多其它内容,感兴趣的同学可以去cppreference上查看。
四 总结
本文分析了C/C++下的enum类型的实际大小,可以看出C++11下enum的大小范围都得到了更好的控制,这样编程时就可以避免潜在的问题。
谢谢阅读,如果有写的不对的地方,请留言指正,谢谢。