similar question, specific packed structs: why size of packed structure different on linux , windows when using gcc?
i'm building shared library linux , windows needs deal well-structured data on network connection. i'm using gcc 4.8.2 on linux, , cross-compiling windows targets using i686-pc-mingw32-gcc 4.8.1.
i've made little program demonstrate issue (note gcc attributes commented out, left them in reference):
#include <stdio.h> #include <stdint.h> #include <stdlib.h> typedef uint16_t word_t; typedef enum //__attribute__((__packed__)) { prio_0 = 0, prio_1, prio_2, prio_3, prio_4, prio_5, prio_6, prio_7, } prio_t; typedef enum //__attribute__((__packed__)) { flag_a = 0, flag_b, } flag_t; typedef struct //__attribute__((__packed__)) { word_t id : 8; prio_t prio : 3; flag_t flag_1 : 1; flag_t flag_2 : 1; flag_t flag_3 : 1; flag_t flag_4 : 1; word_t spare : 1; } recd_t; int main(int argc, char *argv[]) { #define name_width 32 printf("%-*s = %lu\n", name_width, "sizeof(prio_t)", (unsigned long)sizeof(prio_t)); printf("%-*s = %lu\n", name_width, "sizeof(flag_t)", (unsigned long)sizeof(flag_t)); printf("%-*s = %lu\n", name_width, "sizeof(recd_t)", (unsigned long)sizeof(recd_t)); return 0; } i'm compiling linux using: gcc -g -wall test.c -o ./test
and windows: i686-pc-mingw32-gcc -g -wall test.c -o ./test.exe
very straightforward thought. when run on linux, output expect:
sizeof(prio_t) = 4 sizeof(flag_t) = 4 sizeof(recd_t) = 4 but on windows:
sizeof(prio_t) = 4 sizeof(flag_t) = 4 sizeof(recd_t) = 12 so what's deal windows sizes? why different linux in case?
i need pack these enums , structs, issue appears before packing done. when enabled though, results similar:
linux:
sizeof(prio_t) = 1 sizeof(flag_t) = 1 sizeof(recd_t) = 2 windows:
sizeof(prio_t) = 1 sizeof(flag_t) = 1 sizeof(recd_t) = 6
the c specification has informative annex (annex j) summarizes unspecified behavior, undefined behavior, , implementation defined behavior. here's says bit-fields.
j.3 implementation-defined behavior
a conforming implementation required document choice of behavior in each of areas listed in subclause. following implementation-defined:
j.3.9 structures, unions, enumerations, , bit-fields
whether "plain" int bit-field treated signed int bit-field or unsigned int bit-field (6.7.2, 6.7.2.1).
allowable bit-field types other _bool, signed int, , unsigned int (6.7.2.1).
- whether atomic types permitted bit-fields (6.7.2.1).
- whether bit-field can straddle storage-unit boundary (6.7.2.1).
- the order of allocation of bit-fields within unit (6.7.2.1).
- the alignment of non-bit-field members of structures (6.7.2.1). should present no problem unless binary data written 1 implementation read another.
- the integer type compatible each enumerated type (6.7.2.2).
you can draw own conclusions, not use bit-fields in code that's intended portable.
it seems on windows, compiler starts new "unit" every time type changes. in unpacked case, have word_t (2 bytes) followed prio_t (4 bytes), flag_t (4 bytes), , word_t (2 bytes) total of 12 bytes. when packed it's 2,1,1,2 total of 6. if declared fields uint16_t, you'll correct size on windows, still have problem of "the order of allocation of bit-fields within unit" implementation defined.
Comments
Post a Comment