不管枚举值的数量,常量枚举大小

时间:2013-07-26 18:19:14

标签: c++ c enums

为什么enum的大小总是2或4个字节(分别在16位或32位架构上),而不管类型中的枚举数是多少?

编译器是否将enum视为union

6 个答案:

答案 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和常量zeroonetwo的大小均为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,除非枚举值   无法容纳intunsigned int。如果枚举器列表为空,则基础类型为   好像枚举有一个值为0的枚举器。sizeof()的值应用于枚举   type,枚举类型的对象或枚举器,是应用于sizeof()的值   基础类型。

答案 3 :(得分:3)

在我看来,OP已经假定枚举是某种集合,它存储在其中声明的值。这是不正确的。

C / C ++中的枚举只是一个具有严格定义的值范围的数值变量。枚举的名称是数字的别名。

存储大小不受枚举值的影响。存储大小是实现定义的,但主要是sizeof(int)

答案 4 :(得分:1)

enum的大小是“一个至少足以包含声明中指定的任何值的整数类型”。许多编译器只使用int(可能是unsigned),但有些会使用charshort,具体取决于优化或其他因素。少于128个可能值的enum适合charunsigned 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