chapter 6.7.8.10 of ISO/IEC C9899:1999 standard describes how unions with static storage duration are initialized:
If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static storage duration is not initialized explicitly, then:
- if it has pointer type, it is initialized to a null pointer;
- if it has arithmetic type, it is initialized to (positive or unsigned) zero;
- if it is an aggregate, every member is initialized (recursively) according to these rules;
- if it is a union, the first named member is initialized (recursively) according to these rules.
let's assume that we have following code, where actually second member of the union has greater memory footprint than first member of the union:
typedef struct
{
uint32_t a;
uint32_t b;
uint32_t c;
uint32_t d;
} my_structure_t;
typedef union
{
uint8_t *first_member;
my_structure_t later_member;
} my_union_t;
static my_union_t data;
Is it somewhere in C standard defined how memory area occupied by later_member
is going to be initialized ? Because below statements I suspect that this is implementation defined behavior, however I need confirmation and at least links to some gcc, clang, ghs documentation, where it's described.
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1311.pdf
Then comes DR_016 which (in question 2) starts of with: This one is relevant only for hardware on which either null pointer or floating point zero is /not/ represented as all zero bits. It deals with
union { char *p; int i; } x;
and then states:
If the null pointer is represented as, say, 0x80000000, then there is no way to implicitly initialize this object. Either the p member contains the null pointer, or the i member contains 0, but not both. So the behavior of this translation unit is undefined. This is a bad state of affairs. I assume it was not the Committee's intention to prohibit a large class of implicitly initialized unions; this would render a great deal of existing code nonconforming.
Question is mainly targeted to C99 standard, however comparisons with other C standards are more than welcome.
Because only the first named member of a union
is initialized, any additional remaining bytes belonging to other members remain uninitialized and have indeterminate values, and any trailing padding is set to 0.
The same clause you mentioned above is worded slightly differently in C11:
if it is a union, the first named member is initialized (recursively) according to these rules, and any padding is initialized to zero bits;
Since a union
can only contain one member at a time, it is not a problem that bytes corresponding to other members are not set, since the standard says you shouldn't read them anyway.
As per the C99 Standard, the union object that has static storage duration and is not initialized explicitly, the compiler should initialize the first named member (recursively)1). Hence, you should not make any assumption about the value of members other than first member, if their size is bigger than the first named member of union, because as per standard the compiler will only initialize first named member of union and the left over bytes of the members bigger than first named member reside uninitialized.
C Standards do not mention anything about the Data segment (initialized/uninitialized), Stack, Heap etc. These all are architecture/platform specific. For the object initialization (in case of static storage duration), the C Standards only specify what to be initialize to 0
/NULL
and what not and it does not specify which storage duration object go in which segment. The Standard specifications are for compilers and a good compiler is expected to follow them. Typically, the 0
initialized static data goes in .BSS
(Block Started by Symbol), non 0
initialized data goes in .DATA
(Data Segment). So, you may find later_member
structure (which is the second member of union my_union_t
) members value 0
but that may not always be the case.
The C11 Standard includes the specification about padding bytes of union (per 6.7.9p10) [emphasis added]:
10 If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static or thread storage duration is not initialized explicitly, then: ......
......
- if it is a union, the first named member is initialized (recursively) according to these rules, and any padding is initialized to zero bits;
In theory only the pointer to be zeroed, but usually the whole section .bss is zeroed. To make sure just change the order of the members.
User contributions licensed under CC BY-SA 3.0