The sizes of enum types in the following code are different, why? Will the declararation of an enum type will cause gcc to treat it as signed int
? And this feature cause a problem in my project, for example, the size of one enum type is 1 in "file_1.c", but the size of it is 4 in "file_2.c".
My test code:
enum foo foo_test(void);
enum foo {
FOO_0
};
enum bar {
BAR_0
};
int main(int argc, char **argv)
{
printf("sizeof(enum foo) %d, sizeof(enum bar) %d\n", sizeof(enum foo), sizeof(enum bar));
return 0;
}
When I compile it with arm-none-eabi-gcc v4.9.3 in my embedded project
sizeof(enum foo) 4, sizeof(enum bar) 1
.When I compile it with gcc v4.8.3 in Windows
gcc -Wall -o sizeofTest.exe sizeofTest.c
sizeof(enum foo) 4, sizeof(enum bar) 4
.gcc -Wall -fshort-enums -o sizeofTest.exe sizeofTest.c
sizeof(enum foo) 4, sizeof(enum bar) 1
.Two enum names can have same value. For example, in the following C program both 'Failed' and 'Freezed' have same value 0.
An enum type is represented by an underlying integer type. The size of the integer type and whether it is signed is based on the range of values of the enumerated constants. In strict C89 or C99 mode, the compiler allows only enumeration constants with values that will fit in "int" or "unsigned int" (32 bits).
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.
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.
As is so common with the questions asking about peculiar outcomes in c, the reason here is undefined behaviour. The C11 standard draft n1570 6.7.2.3p3:
A type specifier of the form
enum identifier
without an enumerator list shall only appear after the type it specifies is complete.
And of completeness in C11 6.7.2.2p4:
- [...] The enumerated type is incomplete until immediately after the } that terminates the list of enumerator declarations, and complete thereafter.
As a shall in a constraints section was violated, a conforming compiler must output a diagnostics message - however GCC by default isn't a conforming implementation unless you ask it to be -pedantic
:
ISO C forbids forward references to ‘enum’ types [-Werror=pedantic] enum foo foo_test(void); ^
Now, it seems that the compiler there uses the shortest possible enums for any type. Since you used the enum foo
before it was actually defined what was in there, the compiler had to resort to int
for its type, otherwise char
was used. It can be reproduced with -fshort-enums
. Your program prints 4 1
, whereas this program prints 1 1
with -fshort-enums
on my gcc.
#include <stdio.h>
enum foo {
FOO_0
};
enum foo foo_test(void);
enum bar {
BAR_0
};
int main(int argc, char **argv)
{
printf("sizeof(enum foo) %zu, sizeof(enum bar) %zu\n",
sizeof(enum foo), sizeof(enum bar));
return 0;
}
First of all, fix the undefined behaviour in your code. The correct format specifier for the sizeof
expression type is %zu
.
The backing type of an enumerator in C can be char
, int
, or unsigned
. The compiler can pick any of these so long as it is capable of storing all the enumerated values.
So a value of 1 is feasible (as sizeof(char)
is always 1), and you have asked some of your compilers to squeeze the enum
backing types.
The fact that an int
appears to be chosen for the backing type for foo
is due, I think, to your referring to enum foo
before you define it, and your friendly C compiler is using some sort of implicit int
. Such an implicit declaration is no longer standard C and your code is not strictly portable.
Reference: http://en.cppreference.com/w/c/language/enum
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