In both C and C++, the size of an enum
type is implementation-defined, and is the same as the size of some integer type.
A common approach is to make all enum
types the same size as int
, simply because that's typically the type that makes for the most efficient access. Making it a single byte, for example, would save a very minor amount of space, but could require bigger and slower code to access it, depending on the CPU architecture.
In C, enumeration constants are by definition of type int
. So given:
enum foo { zero, one, two };
enum foo obj;
the expression zero
is of type int
, but obj
is of type enum foo
, which may or may not have the same size as int
. Given that the constants are of type int
, it tends to be easier to make the enumerated type the same size.
In C++, the rules are different; the constants are of the enumerated type. But again, it often makes the most sense for each enum
type to be one "word", which is typically the size of int
, for efficiency reasons.
And the 2011 ISO C++ standard added the ability to specify the underlying integer type for an enum
type. For example, you can now write:
enum foo: unsigned char { zero, one, two };
which guarantees that both the type foo
and the constants zero
, one
, and two
have a size of 1 byte. C does not have this feature, and it's not supported by older pre-2011 C++ compilers (unless they provide it as a language extension).
(Digression follows.)
So what if you have an enumeration constant too big to fit in an int
? You don't need 231, or even 215, distinct constants to do this:
#include <limits.h>
enum huge { big = INT_MAX, bigger };
The value of big
is INT_MAX
, which is typically 231-1, but can be as small as 215-1 (32767). The value of bigger
is implicitly big + 1
.
In C++, this is ok; the compiler will simply choose an underlying type for huge
that's big enough to hold the value INT_MAX + 1
. (Assuming there is such a type; if int
is 64 bits and there's no integer type bigger than that, that won't be possible.)
In C, since enumeration constants are of type int
, the above is invalid. It violates the constraint stated in N1570 6.7.2.2p2:
The expression that defines the value of an enumeration constant shall
be an integer constant expression that has a value representable as an
int.
and so a compiler must reject it, or at least warn about it. gcc, for example, says:
error: overflow in enumeration values