[cfe-dev] question about initializing multiple members of unions
Matthew Curtis
mcurtis at codeaurora.org
Wed Sep 11 06:10:34 PDT 2013
I'm investigating an assert in clang compiling the following code:
typedef union {
struct {
int zero;
int one;
int two;
int three;
} a;
int b[4];
} my_agg_t;
my_agg_t agg_instance =
{
.b[0] = 0,
.a.one = 1,
.b[2] = 2,
.a.three = 3,
};
I'm a little uncertain as to what this *should* do.
GCC (4.4.3) produces this assembly:
agg_instance:
.zero 12
.long 3
I had thought that maybe it should produce
agg_instance:
.long 0
.long 1
.long 2
.long 3
Which is the effect that most implementations would have if you
were to execute the analogous assignments:
agg_instance.b[0] = 0,
agg_instance.a.one = 1,
agg_instance.b[2] = 2,
agg_instance.a.three = 3,
Experimenting with various orderings of the designated initializers
leads me to believe that whenever the member of the union being
initialized changes, GCC discards any previous member initializations.
For clang, this ordering
my_agg_t agg_instance =
{
.a.one = 1,
.b[0] = 0,
.a.three = 3,
.b[2] = 2,
};
does not assert and produces
agg_instance:
.long 0
.long 1
.long 2
.long 3
Though after stepping through some of the code I think this may be
accidental.
Reading sections 6.7.2.1 and 6.7.8 of the spec, it's not clear to me
exactly what the behavior should be, though I could see how GCC's
behavior would be considered compliant.
Thoughts?
Matthew Curtis
----------------------------------------------------------------------
BTW, Here are the portions of the C99 spec[0] that I thought were
relevant
6.7.2.1 Structure and union specifiers
14 [...] The value of at most one of the members can be stored in a
union object at any time. [...]
6.7.8 Initialization
17 [...] a designation causes the following initializer to begin
initialization of the subobject described by the designator.
Initialization then continues forward in order, beginning with the
next subobject after that described by the designator. 128)
19 The initialization shall occur in initializer list order, each
initializer provided for a particular subobject overriding any
previously listed initializer for the same subobject; 130) [...]
128) After a union member is initialized, the next object is not the
next member of the union; instead, it is the next subobject of an
object containing the union.
130) Any initializer for the subobject which is overridden and so not
used to initialize that subobject might not be evaluated at all.
[0] http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf
More information about the cfe-dev
mailing list