Different sizes of the same type of enumeration

The sizes of enum types in the following code are different, why? Will an enumeration type declaration cause gcc to process it as a signed int ? And this function causes a problem in my project, for example, the size of one type of enumeration is 1 in the file "file_1.c", but its size is 4 in "file_2.c".

My test code is:

 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

    • output sizeof(enum foo) 4, sizeof(enum bar) 1 .
  • When will I compile it with gcc v4.8.3 on Windows

    • compile with gcc -Wall -o sizeofTest.exe sizeofTest.c
      • output sizeof(enum foo) 4, sizeof(enum bar) 4 .
    • compile with gcc -Wall -fshort-enums -o sizeofTest.exe sizeofTest.c
      • output sizeof(enum foo) 4, sizeof(enum bar) 1 .
+5
source share
4 answers

As is often the case with questions about specific results in c , the reason here is undefined behavior . Standard project C11 n1570 6.7.2.3p3 :

  1. Form type specifier

     enum identifier 

    no list of enumerators should appear only after the type that it defines is completed.

And completeness in C11 6.7.2.2p4 :

  1. [...] The enumerated type is incomplete until the moment immediately following}, which completes the list of declarations of the enumerator and ends after that.

As it was violated in the restrictions section, the corresponding compiler should output a diagnostic message - however, GCC is by default not an appropriate 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 uses the shortest possible enumerations for any type. Since you used enum foo , before it was actually determined what was there, the compiler had to use int for its type, otherwise char used. It can be played using -fshort-enums . Your program prints 4 1 , while 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; } 
+6
source

First of all, fix the undefined behavior in your code. The correct format specifier for the expression type sizeof is %zu .

The type of enumerator support in C can be char , int or unsigned . The compiler can select any of them if it is able to store all the listed values.

So a value of 1 is possible (since sizeof(char) always 1), and you asked some of your compilers to compress enum support types.

The fact that a int apparently selected for the support type for foo , in my opinion, relates to your call to enum foo before you define it, and your friendly C compiler uses some kind of implicit int . Such an implicit declaration is no longer standard C, and your code is not strictly portable.

Link: http://en.cppreference.com/w/c/language/enum

+4
source

This behavior is undefined.

You must use %zu to make printf() format for a value of type size_t .

If the size of the value is different from the int value, the code in printf() will read the varargs argument incorrectly and get an incorrect idea of ​​its value ( va_arg(args, int); instead of va_arg(args, size_t);

+2
source

The answer is actually quite simple.

Since you have a return type for the enumeration of the prototype function, the compiler assumes it as an int and its size depends on the hardware (in your case, 4 bytes). This is done for optimization purposes. For another, it is stored in the smallest possible data type. (OO and / or -fshort-enums optimizations were probably used)

For coders with real programming experience, this behavior is well known, and for this reason it is not necessary to declare functions as returning enumerations if you want to keep them short.

For standard C fanatics uint8_t foo(); and return FOO_0; may be unacceptable, but programming is a real, living, and practical science.

-1
source

Source: https://habr.com/ru/post/1271149/


All Articles