C ++中的枚举类型数据的大小是多少?


67

这是一个C ++面试测试问题而不是作业。

#include <iostream>
using namespace std;
enum months_t { january, february, march, april, may, june, july, august, september,    
  october, november, december} y2k;

 int main ()
  {
    cout << "sizeof months_t is  " << sizeof(months_t) << endl;
    cout << "sizeof y2k is  " << sizeof(y2k) << endl;
    enum months_t1 { january, february, march, april, may, june, july, august,    
       september, october, november, december} y2k1;
    cout << "sizeof months_t1 is  " << sizeof(months_t1) << endl;
    cout << "sizeof y2k1 is  " << sizeof(y2k1) << endl;
 }

输出:

sizeof months_t是4
sizeof
y2k是4
sizeof months_t1是4 sizeof y2k1是4

为什么所有这4个字节的大小都是?不是12 x 4 = 48个字节?
我知道联合元素占据相同的内存位置,但这是一个枚举。


10
没有人怎么提到枚举类?我希望C ++爱好者在这样的问题上超越职责范围。
马特·乔纳

3
取消OP的操作是第一要务。但是,没有什么可以阻止您加入枚举类。
ObscureRobot 2011年

1
@MattJoiner您的意思是在C ++ 11中可以指定枚举的基础类型吗,即它模仿的整数类型?例如enum month : char { january, ... };。类枚举(又名作用域枚举)是为常量创建封闭名称空间的另一种类。问题是类枚举始终是固定的基础类型(int如果未指定)。
rodrigo

2
@MattJoiner:没有人提到枚举类,因为这是C ++ 11的功能,他没有询问C ++ 11的功能。
Nicol Bolas

2
而且,这与本案完全无关。这是关于枚举数与类型大小之间的关系(它是对数的,不是线性的)。
MSalters 2011年

Answers:


51

大小为4个字节,因为enum储存为int。仅使用12个值,您实际上只需要4位,但是32位机器比32位机器更有效地处理32位数量。

0 0 0 0  January
0 0 0 1  February
0 0 1 0  March
0 0 1 1  April
0 1 0 0  May
0 1 0 1  June
0 1 1 0  July
0 1 1 1  August
1 0 0 0  September
1 0 0 1  October
1 0 1 0  November
1 0 1 1  December
1 1 0 0  ** unused **
1 1 0 1  ** unused **
1 1 1 0  ** unused **
1 1 1 1  ** unused **

如果没有枚举,您可能会倾向于使用原始整数来表示月份。那会行之有效,但会使您的代码难以阅读。使用枚举,您可以获得有效的存储和可读性。


我认为该标准希望枚举与整数相同。C ++ 11引入了枚举类。
Basile Starynkevitch

可能是这样。有被引用吗?
ObscureRobot 2011年

2
否-四位变量可以代表16个不同的值。您每个月不需要额外的四位。如果您想将月份存储为位向量,则只需12位。那仍然可以安全地容纳在4个字节之内。
ObscureRobot 2011年

7
原始答案是正确的。枚举必须至少为一个字节,但是编译器可以自由使用更多的内存。并且由于可以在数组中包含枚举,因此sizeof必须是对齐方式的倍数。您不能将1字节的枚举对齐为4字节。
MSalters 2011年

4
在C ++ 11之前,它取决于sizeof(enum_value)是“非常糟糕的主意[TM]”
Dale Wilson

118

这是一个C ++面试测试问题而不是作业。

然后,您的面试官需要重新了解C ++标准的工作原理。我引用

对于基础类型不固定的枚举,基础类型是整数类型,可以表示该枚举中定义的所有枚举数。

整个“其基础类型未固定”部分来自C ++ 11,其余部分均为标准C ++ 98/03。总之,sizeof(months_t)4.它不是2任一。它可以是任何的。该标准没有说明应该是多大。只是它应该足够大以适合任何枚举器。

为什么所有大小都是4个字节?不是12 x 4 = 48个字节?

因为枚举不是变量。枚举的成员不是实际变量;它们只是#define的半类型安全形式。它们是一种以易于阅读的格式存储数字的方式。编译器会将枚举器的所有用法转换为实际数值。

枚举器只是谈论数字的另一种方式。january是的简写0。0占用多少空间?这取决于您存储的内容。


11
这是一个很好的答案,不容忽视。尽管我的回答提供了理解枚举的基础,但是,如果您希望通过此类面试问题,则确实需要在这个级别上掌握枚举。
ObscureRobot 2011年

感谢@Bolas,但您避开了为什么编译器选择4 bytes而不是遵循标准要求的最小值,即此处的1 byte(12个不同的枚举数:)4bits。标准中还有第二个词,这太奇怪了:this type is not larger than int unless the value of an enumerator cannot fit in an int这告诉我编译器实现者渴望扩展类型,即使不需要,这也限制了他们的热情。
v.oddou

@ v.oddou:那为什么它不能选择long long;这不是选择它的原因int。之所以选择int它,是因为根据标准,这是一个有效的选择,而且感觉很不错。除此之外没有其他原因。
尼科尔·波拉斯

大声笑,您会在编译器中实现某些东西,因为您感觉像吗?我敢肯定,这是boost::int_value_t<V>::leastvsboost::int_value_t<V>::fast的选择。或面对枚举数更改的二进制兼容性健壮性。
v.oddou

@ v.oddou:我的观点是选择取决于实现。您无法预测或依靠它。这就是为什么我们现在允许人们指定实际类型的原因。
Nicol Bolas '18

10

这取决于。该标准仅要求其大小足以容纳所有值,因此从形式上讲,枚举之类的大小enum foo { zero, one, two };仅需一个字节。但是,大多数实现使这些枚举与int一样大(在现代硬件上速度更快;此外,与C兼容(枚举基本上是由int修饰)是需要的。但是请注意,C ++允许具有int范围之外的初始化程序的枚举,对于这些枚举,其大小当然也将更大。例如,如果您拥有enum bar { a, b = 1LL << 35 };枚举,则即使在具有32位整数的系统上,您的枚举也将大于32位(最有可能是64位)(请注意,在C中,该枚举是不允许的)。


6

枚举有点像int类型(类型)的typedef。

因此,您在此处定义的类型具有12个可能的值,但是单个变量仅具有这些值之一。

可以这样考虑,当您定义一个枚举时,基本上是在定义另一种分配int值的方式。

在您提供的示例中,january是0的另一种说法,feb是1的另一种说法,以此类推,直到12月是11的另一种说法。



4

随着我现在老化的Borland C ++ Builder编译器,枚举可以为1,2或4字节,尽管它确实有一个标志,您可以翻转以强制它使用int。

我猜这是特定于编译器的。


2
使用gcc时,该行为受到重视-枚举默认为int,但是该标志-fshort-enums将枚举使用的空间缩短到几乎没有必要。(尽管这可能不太理想。)
Arjun Menon 2016年

3

我喜欢来自EdX(Microsoft:DEV210x C ++简介)中的类似问题的解释:

“枚举将天的字面值表示为整数。参照数字类型表,您会看到一个int占用4个字节的内存。如果存储了整个枚举,则7天x 4字节每个将需要28字节的内存。编译器仅使用枚举的单个元素,因此内存中的大小实际上是4个字节。”


这是没有意义的。
v.oddou

1

枚举几乎是整数。简化很多

enum yourenum { a, b, c };

几乎像

#define a 0
#define b 1
#define c 2

当然,这不是真的。我试图解释枚举是某种编码...

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.