what is the size of an enum type data in C++?
Asked Answered
H

9

82

This is a C++ interview test question not homework.

#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;
 }

Output:

sizeof months_t is 4
sizeof y2k is 4
sizeof months_t1 is 4
sizeof y2k1 is 4

Why is the size of all of these 4 bytes? Not 12 x 4 = 48 bytes?
I know union elements occupy the same memory location, but this is an enum.

Hypnology answered 13/11, 2011 at 23:13 Comment(5)
How did nobody mention enum classes? I'd expect C++ enthuasiasts to go beyond the call of duty on a question like this.Palmary
Deconfusing the OP is the first order of the day. Nothing is stopping you from weighing in on enum classes though.Murcia
@MattJoiner Do you mean that in C++11 you can specify the underlying type of an enum, that is which integral type it mimics? For instance enum month : char { january, ... };. Class enums, aka scoped enums, are another variety of classes that create an enclosing namespace for its constants. The thing is that class enums are always of a fixed underlying type (int if none specified).Earthiness
@MattJoiner: No one mentioned enum classes because that's a C++11 feature, and he didn't ask about C++11 features.Lenticularis
Also, it's utterly irrelevant to this case. That's about the relation between the number of enumerators and the size of the type (which is logarithmic, not linear).Glockenspiel
M
61

In your compiler, the size is four bytes because the enum is stored as an int. With only 12 values, you really only need 4 bits, but 32 bit machines process 32 bit quantities more efficiently than smaller quantities.

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 **

Without enums, you might be tempted to use raw integers to represent the months. That would work and be efficient, but it would make your code hard to read. With enums, you get efficient storage and readability.

Other compilers could use a byte, int16, uint16 int or uint as long as the variable can contain all the values of the enum.

Murcia answered 13/11, 2011 at 23:16 Comment(8)
I think the standard wants enum to be the same as integer. C++11 introduced enum classes.Indicant
That could be the case. Got a cite?Murcia
Also: even if C allowed an enum to be a byte, a 32 bit compiler would most likely align your enum to 32-bit boundaries, eating up 32 bits anyway :)Murcia
@ObscureRobot, in this way, the total bits should be 4 x 12 = 48 bits/ 8 = 6 bytes not 4 bytes !!!Hypnology
No - a four bit variable can represent any of sixteen different values. You don't need an additional four bits for each month. If you wanted to store your months as a bit vector, you'd only need 12 bits. That would still fit safely within 4 bytes.Murcia
The original answer is correct. The enum must be at least one byte, but a compiler is free to use more memory. And since you can have enums in an array, sizeof must be a multiple of the alignment. You can't have a one-byte enum aligned o 4 bytes.Glockenspiel
It makes a difference if you #pragma pack(1) and plan to send the data across a network connection or store it in a disk file where it might be read by code compiled with a different (version of the) compiler.Jackal
Pre C++11 it is a "Very Bad Idea [TM]" to depend on sizeof(enum_value)Jackal
L
141

This is a C++ interview test question not homework.

Then your interviewer needs to refresh his recollection with how the C++ standard works. And I quote:

For an enumeration whose underlying type is not fixed, the underlying type is an integral type that can represent all the enumerator values defined in the enumeration.

The whole "whose underlying type is not fixed" part is from C++11, but the rest is all standard C++98/03. In short, the sizeof(months_t) is not 4. It is not 2 either. It could be any of those. The standard does not say what size it should be; only that it should be big enough to fit any enumerator.

why the all size is 4 bytes ? not 12 x 4 = 48 bytes ?

Because enums are not variables. The members of an enum are not actual variables; they're just a semi-type-safe form of #define. They're a way of storing a number in a reader-friendly format. The compiler will transform all uses of an enumerator into the actual numerical value.

Enumerators are just another way of talking about a number. january is just shorthand for 0. And how much space does 0 take up? It depends on what you store it in.

Lenticularis answered 14/11, 2011 at 0:11 Comment(6)
This is an excellent answer that should not be overlooked. Although my answer provides the basics for understanding an enum, you really need to be able to grasp an enum at this level if you expect to pass this sort of interview question.Murcia
thanks @Bolas but you shunned away why the compiler chose 4 bytes instead of the minimum that respects the standard requirement, which is 1 byte (12 distinct enumerators:4bits) here. And there is a second phrase in the standard, that is super weird: this type is not larger than int unless the value of an enumerator cannot fit in an int this tells me that compiler implementors were eager to enlarge the type even if not needed, this second phrase limits their zeal.Recrement
@v.oddou: That why it couldn't choose long long; that's not why it chose int. It chose int because it was a valid choice according to the standard and it felt like it. No other reason than that.Lenticularis
Lol, you'd implement stuff in your compiler because you feel like it ? I'm sure it's a boost::int_value_t<V>::least vs boost::int_value_t<V>::fast kind of choice. Or a binary compatibility robustness in the face of enumerator changes.Recrement
@v.oddou: My point is that the choice is implementation-dependent. It's not something you can predict or rely on. That's part of why we now allow people to specify the actual type.Lenticularis
But certainly. Though every choice can be explained. If not by the standard, the compiler implementers know.Recrement
M
61

In your compiler, the size is four bytes because the enum is stored as an int. With only 12 values, you really only need 4 bits, but 32 bit machines process 32 bit quantities more efficiently than smaller quantities.

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 **

Without enums, you might be tempted to use raw integers to represent the months. That would work and be efficient, but it would make your code hard to read. With enums, you get efficient storage and readability.

Other compilers could use a byte, int16, uint16 int or uint as long as the variable can contain all the values of the enum.

Murcia answered 13/11, 2011 at 23:16 Comment(8)
I think the standard wants enum to be the same as integer. C++11 introduced enum classes.Indicant
That could be the case. Got a cite?Murcia
Also: even if C allowed an enum to be a byte, a 32 bit compiler would most likely align your enum to 32-bit boundaries, eating up 32 bits anyway :)Murcia
@ObscureRobot, in this way, the total bits should be 4 x 12 = 48 bits/ 8 = 6 bytes not 4 bytes !!!Hypnology
No - a four bit variable can represent any of sixteen different values. You don't need an additional four bits for each month. If you wanted to store your months as a bit vector, you'd only need 12 bits. That would still fit safely within 4 bytes.Murcia
The original answer is correct. The enum must be at least one byte, but a compiler is free to use more memory. And since you can have enums in an array, sizeof must be a multiple of the alignment. You can't have a one-byte enum aligned o 4 bytes.Glockenspiel
It makes a difference if you #pragma pack(1) and plan to send the data across a network connection or store it in a disk file where it might be read by code compiled with a different (version of the) compiler.Jackal
Pre C++11 it is a "Very Bad Idea [TM]" to depend on sizeof(enum_value)Jackal
O
11

It depends. The standard only demands that it is large enough to hold all values, so formally an enum like enum foo { zero, one, two }; needs to only be one byte large. However most implementations make those enums as large as ints (that's faster on modern hardware; moreover it's needed for compatibility with C where enums are basically glorified ints). Note however that C++ allows enums with initializers outside of the int range, and for those enums the size will of course also be larger. For example, if you have enum bar { a, b = 1LL << 35 }; then your enum will be larger than 32 bits (most likely 64 bits) even on a system with 32 bit ints (note that in C that enum would not be allowed).

Outgoings answered 13/11, 2011 at 23:26 Comment(0)
S
8

In C++11 you can use

enum myenum : uint8_t 
{
  ...
}
myenum myvar;

and you will get the garantuee that sizeof(myvar)==1... this feature is named "sized enum", see https://en.cppreference.com/w/cpp/language/enum (check the parts marked as (since C++11))

Sherrisherrie answered 6/4, 2023 at 16:35 Comment(0)
I
7

An enum is kind of like a typedef for the int type (kind of).

So the type you've defined there has 12 possible values, however a single variable only ever has one of those values.

Think of it this way, when you define an enum you're basically defining another way to assign an int value.

In the example you've provided, january is another way of saying 0, feb is another way of saying 1, etc until december is another way of saying 11.

Ibidem answered 13/11, 2011 at 23:18 Comment(0)
L
5

Because it's the size of an instance of the type - presumably enum values are stored as (32-bit / 4-byte) ints here.

Levis answered 13/11, 2011 at 23:16 Comment(0)
L
4

With my now ageing Borland C++ Builder compiler enums can be 1,2 or 4 bytes, although it does have a flag you can flip to force it to use ints.

I guess it's compiler specific.

Lacquer answered 25/4, 2012 at 16:51 Comment(1)
With gcc, the behavior is revered -- enums default to int, but the flag -fshort-enums shortens the space used by the enum to what's barely necessary. (Although this is likely less optimal.)Earflap
S
2

I like the explanation From EdX (Microsoft: DEV210x Introduction to C++) for a similar problem:

"The enum represents the literal values of days as integers. Referring to the numeric types table, you see that an int takes 4 bytes of memory. 7 days x 4 bytes each would require 28 bytes of memory if the entire enum were stored but the compiler only uses a single element of the enum, therefore the size in memory is actually 4 bytes."

Steiner answered 22/3, 2017 at 19:40 Comment(1)
that makes no sense.Recrement
I
0

An enum is nearly an integer. To simplify a lot

enum yourenum { a, b, c };

is almost like

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

Of course, it is not really true. I'm trying to explain that enum are some kind of coding...

Indicant answered 13/11, 2011 at 23:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.