Even though GCC takes advantage of tail padding when laying out structures with flexible array members, in C mode it allocates excess storage for statically initialized objects of such structs. In the test case below, thanks to tail padding, sizeof (struct A) is sufficiently large to store each of a0 through a3. But as the assembly output shows, the variables occupy more storage than necessary. $ cat a.c && gcc -O2 -S -Wall -Wextra -o /dev/stdout -xc a.c | grep -e \.size struct A { __INT64_TYPE__ i64; __INT16_TYPE__ i16; __INT16_TYPE__ a16[]; }; struct A a0 = { 0, 1 }; struct A a1 = { 1, 1, { 1 } }; struct A a2 = { 2, 1, { 1, 2 } }; struct A a3 = { 3, 1, { 1, 2, 3 } }; struct A a4 = { 4, 1, { 1, 2, 3, 4 } }; .size a4, 24 .size a3, 22 .size a2, 20 .size a1, 18 .size a0, 16 G++ on the other hand, allocates the same amount of space regardless of the size of the initializer: $ gcc -O2 -S -Wall -Wextra -o /dev/stdout -xc++ a.c | grep -e \.size .size a4, 16 .size a3, 16 .size a2, 16 .size a1, 16 .size a0, 16 Clang allocates just the right amount, i.e., 16 bytes for a0 through a3 and 24 bytes for a4.
Note the C++ sizes was recorded as PR 102295 .
Note the .size does match up with what GCC outputs though: e.g. a1: .size a1, 18 a1: .xword 1 .hword 1 .hword 1 .zero 6 that is size of 18. Basically gcc's padding is always 6 in size and not changing based on the size that is needed there. This is also normally how you get the size when allocating dynamically too: sizeof(struct A) + N*sizeof(__INT16_TYPE__).
*** Bug 109956 has been marked as a duplicate of this bug. ***