I tried some gcc compilers to see if the default enum size is short (at least one byte, as forced with -fshort-enums
) or no-short (at least 4 bytes, as forced with -fno-short-enums
):
user@host:~$ echo '_Static_assert(4 == sizeof(enum{E}), "enum size is not 4");' | x86_64-linux-gnu-gcc -fsyntax-only -xc - && echo "OK, enum size is 4 on x86_64-linux-gnu"
OK, enum size is 4 on x86_64-linux-gnu
user@host:~$ echo '_Static_assert(4 == sizeof(enum{E}), "enum size is not 4");' | arm-linux-gnueabihf-gcc -fsyntax-only -xc - && echo "OK, enum size is 4 on arm-linux-gnueabihf"
OK, enum size is 4 on arm-linux-gnueabihf
user@host:~$ echo '_Static_assert(4 == sizeof(enum{E}), "enum size is not 4");' | /opt/Atollic_TrueSTUDIO_for_STM32_x86_64_9.1.0/ARMTools/bin/arm-atollic-eabi-gcc -fsyntax-only -xc -
<stdin>:1:1: error: static assertion failed: "enum size is not 4"
user@host:~$ echo '_Static_assert(4 == sizeof(enum{E}), "enum size is not 4");' | /opt/Atollic_TrueSTUDIO_for_STM32_x86_64_9.1.0/ARMTools/bin/arm-atollic-eabi-gcc -fno-short-enums -fsyntax-only -xc - && echo "OK, enum size is 4 on arm-atollic-eabi with -fno-short-enums"
OK, enum size is 4 on arm-atollic-eabi with -fno-short-enums
As you can see, short is the default on embedded targets, while no-short is the default on hosted platforms. This makes sense to improve binary compatibility on hosted platforms. Now:
What is the rule that tells me if enums will be short depending on the configure options when building gcc and where is it documented?
Edit:
As pointed out in Lundin's answer, the gcc manual states that
On some targets,
-fshort-enums
is the default; this is determined by the ABI.
My question is: How is the dependency on the ABI, and where is it documented? Do the gcc sources contain a kind of database that map architectures (e.g. arm-linux-gnueabihf) to ABIs and a kind of database that specifies all the options (e.g. short enums or no-short enums) for each ABI? Or is it all hard-coded magic scattered throughout the whole source tree?
The C standard specifies that enums are integers, but it does not specify the size. Once again, that is up to the people who write the compiler. On an 8-bit processor, enums can be 16-bits wide. On a 32-bit processor they can be 32-bits wide or more or less.
In C language, an enum is guaranteed to be of size of an int . There is a compile time option ( -fshort-enums ) to make it as short (This is mainly useful in case the values are not more than 64K). There is no compile time option to increase its size to 64 bit.
In the gcc manual, look for implementation-defined behavior. Chapter 4.9.
The integer type compatible with each enumerated type (C90 6.5.2.2, C99 and C11 6.7.2.2).
Normally, the type is
unsigned int
if there are no negative values in the enumeration, otherwiseint
. If-fshort-enums
is specified, then if there are negative values it is the first ofsigned char
,short
andint
that can represent all the values, otherwise it is the first ofunsigned char
,unsigned short
andunsigned int
that can represent all the values.On some targets,
-fshort-enums
is the default; this is determined by the ABI.
The italic part is cited from the C standard's implementation-defined behavior. As you can see, the type is adaptive depending on which enumeration constants there are. It need not have the same size consistently through your program, for different enum
types.
Optimization settings might matter, since 4 bytes enum
might be faster than 1 byte enum on some machines.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With