Ivan Ivan - 30 days ago 10
C Question

different size of the same enum type

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


    • the output is
      sizeof(enum foo) 4, sizeof(enum bar) 1
      .


  • When I compile it with gcc v4.8.3 in Windows


    • compile with
      gcc -Wall -o sizeofTest.exe sizeofTest.c



      • the output is
        sizeof(enum foo) 4, sizeof(enum bar) 4
        .


    • compile with
      gcc -Wall -fshort-enums -o sizeofTest.exe sizeofTest.c



      • the output is
        sizeof(enum foo) 4, sizeof(enum bar) 1
        .




Answer Source

As is so common with the questions asking about peculiar outcomes in , the reason here is undefined behaviour. The C11 standard draft n1570 6.7.2.3p3:

  1. 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:

  1. [...] The enumerated type is incomplete until immediately after the } that terminates the list of enumerator declarations, and complete thereafter.

A shall in constraint was violated, and the compiler needs to output diagnostics - 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;
}