SLAU132Y September 2004 – June 2021
In the following declaration,
enum e
is an enumerated type. Each of a
and b
are enumeration
constants.
enum e { a, b=N };
Each enumerated type is assigned an integer type that can hold all of the enumeration constants. This integer type is the "underlying type." The type of each enumeration constant is also an integer type, and in C might not be the same type. Be careful to note the difference between the underlying type of an enumerated type and the type of an enumeration constant.
The size and signedness chosen for the enumerated type and each enumeration constant depend on the values of the enumeration constants and whether you are compiling for C or C++. C++11 allows you to specify a specific type for an enumeration type; if such a type is provided, it will be used and the rest of this section does not apply.
In C++ mode, the compiler allows enumeration constants up to the largest integral type (64 bits). The C standard says that all enumeration constants in strictly conforming C code (C89/C99/C11) must have a value that fits into the type "int;" however, as an extension, you may use enumeration constants larger than "int" even in C mode.
You may control the strategy for picking enumerated types by using either the --enum_type command line option, or by using an attribute, or both. If you use the --enum_type=packed option, the compiler uses the smallest type it can for the enumerated type. If you use the --enum_type=unpacked option (the default), it will use the smallest type no smaller than "int." You can use the "packed" or "unpacked" attribute to set the strategy for a single enum type; this overrides the value of the command line option.
For example, this enumerated type will be of type unsigned char, even if --enum_type=unpacked is specified on the command line.
enum { a, b, c } __attribute__((packed));
This enumerated type will be of type unsigned int, even if --enum_type=packed is specified on the command line.
enum { a, b, c } __attribute__((unpacked));
You can use the packed/unpacked attribute on enumerated types in header files to ensure that an enumerated type is always the same size, even if the --enum_type option is changed on the command line.
For the enumerated type, the compiler selects the first type in the following list that is big enough and of the correct sign to represent all of the values of the enumeration constants. The "short" types are not used because they are the same size as the "int" type.
For example, by default (--enum_type=unpacked) this enumerated type will have "unsigned int" as its underlying type:
enum ui { a, b, c };
But this one will have "signed int" as its underlying type:
enum si { a, b, c, d = -1 };
And this one will have "signed long" as its underlying type:
enum sl { a, b, c, d = -1, e = UINT_MAX };
For C++, the enumeration constants are all of the same type as the enumerated type.
For C, the enumeration constants are assigned types depending on their value. All enumeration constants with values that can fit into "int" are given type "int," even if the underlying type of the enumerated type is smaller than "int." All enumeration constants that don't fit in an "int" are given the same type as the underlying type of the enumerated type. This means that some enumeration constants may have a different size and signedness than the enumeration type.