为什么enum
的大小总是2或4个字节(分别在16位或32位架构上),而不管类型中的枚举数是多少?
编译器是否将enum
视为union
?
答案 0 :(得分:20)
在C和C ++中,enum
类型的大小是实现定义的,并且与某个整数类型的大小相同。
一种常见的方法是使所有enum
类型与int
的大小相同,因为这通常是实现最有效访问的类型。例如,将其设为单个字节可以节省非常小的空间,但可能需要更大更慢的代码才能访问它,具体取决于CPU架构。
在C中,枚举常量按类型int
的定义。所以给出:
enum foo { zero, one, two };
enum foo obj;
表达式zero
的类型为int
,但obj
的类型为enum foo
,其大小可能与int
相同或不同。鉴于常量的类型为int
,因此更容易使枚举类型具有相同的大小。
在C ++中,规则是不同的;常量是枚举类型。但同样,出于效率原因,每个enum
类型通常最有意义的是一个“单词”,通常大小为int
。
2011 ISO C ++标准增加了为enum
类型指定基础整数类型的功能。例如,您现在可以写:
enum foo: unsigned char { zero, one, two };
保证类型foo
和常量zero
,one
和two
的大小均为1个字节。 C没有此功能,2011年以前的C ++编译器不支持它(除非它们将其作为语言扩展提供)。
(Digression跟随。)
那么,如果枚举常数太大而无法适应int
,那该怎么办?你不需要2 31 ,或者甚至2 15 ,这是不同的常数:
#include <limits.h>
enum huge { big = INT_MAX, bigger };
big
的值是INT_MAX
,通常为2 31 -1,但可以小到2 15 -1 (32767)。 bigger
的值隐含big + 1
。
在C ++中,这没关系;编译器将只选择huge
的基础类型,其大小足以容纳值INT_MAX + 1
。 (假设存在这样的类型;如果int
是64位并且没有大于那的整数类型,那将是不可能的。)
在C中,由于枚举常量的类型为int
,因此上述内容无效。它违反了N1570 6.7.2.2p2:
定义枚举常量值的表达式 是一个整数常量表达式,具有可表示为的值 的 INT 强>
所以编译器必须拒绝它,或至少警告它。例如,gcc说:
错误:枚举值溢出
答案 1 :(得分:9)
枚举不是一种结构,它只是一种给一组整数赋值的方法。具有此类型的变量的大小就是基础整数类型的大小。
答案 2 :(得分:8)
枚举的大小是实现定义的 - 允许编译器选择它想要的任何大小,只要它足够大以适合所有值。一些编译器选择对所有枚举类型使用4字节枚举,而一些编译器将选择可以适合枚举值的最小类型(例如,1,2或4个字节)。 C和C ++语言标准允许这两种行为。
来自C99§6.7.2.2/ 4:
每个枚举类型应与
char
,有符号整数类型或 无符号整数类型。类型的选择是实现定义的, 110)但应该是 能够表示枚举中所有成员的值。
来自C ++03§7.2/ 5:
枚举的基础类型是一个整数类型,可以表示所有枚举值 在枚举中定义。它是实现定义的,其中整数类型用作底层类型 对于枚举,除非基础类型不应大于
int
,除非枚举值 无法容纳int
或unsigned int
。如果枚举器列表为空,则基础类型为 好像枚举有一个值为0的枚举器。sizeof()
的值应用于枚举 type,枚举类型的对象或枚举器,是应用于sizeof()
的值 基础类型。
答案 3 :(得分:3)
在我看来,OP已经假定枚举是某种集合,它存储在其中声明的值。这是不正确的。
C / C ++中的枚举只是一个具有严格定义的值范围的数值变量。枚举的名称是数字的别名。
存储大小不受枚举值的影响。存储大小是实现定义的,但主要是sizeof(int)
。
答案 4 :(得分:1)
enum
的大小是“一个至少足以包含声明中指定的任何值的整数类型”。许多编译器只使用int
(可能是unsigned
),但有些会使用char
或short
,具体取决于优化或其他因素。少于128个可能值的enum
适合char
(unsigned char
为256),并且您必须有32768(或65536)个值才能溢出short
在大多数现代系统中,有两个或40亿个值可以超过int
。
enum
基本上只是定义一堆不同常量的更好方法。而不是:
#define FIRST 0
#define SECOND 1
...
你只是:
enum myenum
{ FIRST,
SECOND,
...
};
它有助于避免错误地分配重复值,并且无需关心特定值(除非您确实需要)。
答案 5 :(得分:0)
当较小的类型适合所有值时,使enum
类型小于int
的一个大问题是它会使翻译单元的ABI依赖于枚举常量的数量。例如,假设您有一个库使用带有256个常量的enum
类型作为其公共接口的一部分,并且编译器选择将该类型表示为单个字节。现在假设您向库中添加了一个新功能,现在需要257个常量。编译器必须切换到新的大小/表示,现在为旧接口编译的所有目标文件都与更新的库不兼容;你将不得不重新编译所有内容以使其再次运行。
因此,任何理智的实现始终对int
类型使用enum
。