És az u testx = { 1 }; esetén mi történik?
Természetesen hibát dob a fordító.
A C szabvány szerint a "{ 0 }" egy speciális inicializáló (ún. "universal zero initializer"), ami mindent nullára kell (kéne), hogy inicializáljon, akkor is, ha nem írod ki a tagokat.
Ezzel szemben a "{ 1 }", nem speciális, tehát helyesen vagy "{ .c = 1 }" vagy "{ .i = 1 }". Little endian gépeken mondjuk ugyanaz az eredmény, de big endian gépeken nagyon nem.
(C99 esetén már elfogadja a "{ 1 }"-et, ekkor ezt úgy veszi, hogy az első union tag kap értéket, tehát egy bájtnyi 1-es. Szerintem pont ezt szopták be, emiatt az első elemesdi miatt van az, hogy a "{ 0 }" csak az első tag méretéig nulláz most, holott a szabvány nem ezt mondja.)
Az már a .data-ba megy, nem a .bss-be...
A szabvány (81. oldal) szerint ha van részben inicializáció, akkor az explicit ki nem írt tagokat üresnek (azaz nullának) kell inicializálni a statikus tárolási osztály méretének erejéig (tehát C99-től is elvárás (lenne), hogy ha csak első tagot inicializálod az "{ 1 }"-el, akkor az egy bájtnyi 1-es utánni rész nulla legyen).
If there are fewer initializers in a list than there are members of an aggregate, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.
és (kiemelés tőlem)
If an object that has static storage duration is not initialized explicitly, it is initialized implicitly as if every member that has arithmetic type were assigned 0 and every member that has pointer type were assigned a null pointer constant.
Igen, a gcc 15.1 bugos és megsérti a C szabványt (még a C23-at is, bár azt is faszkalapok írták, így nem egyértelmű a szövegből, miért is kéne különbségnek lennie a "{}" és a "{0}" között. A C89-nél nincs ilyen probléma, ott feketén-fehéren leírták, hogy a "{0}" mit jelent).
A vicc az egészben, hogy a Clang-ban pont most javították, hogy az egész union-t nullázza, ne csak az első elem méretéig...