Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Initialization of anonymous structures and unions

408 views
Skip to first unread message

Stephen Heumann

unread,
Oct 18, 2021, 9:44:01 PM10/18/21
to
I'm trying to figure out how initialization of anonymous structures and
unions is supposed to work, particularly when using brace-enclosed
initializer lists without designators. Quotes below are from N2596
(the latest available C23 draft), but except as noted the wording is
the same back to C11.

6.7.2.1 p15 defines anonymous structures and unions as follows:
"An unnamed member whose type specifier is a structure specifier with
no tag is called an anonymous structure; an unnamed member whose type
specifier is a union specifier with no tag is called an anonymous
union. The members of an anonymous structure or union are considered to
be members of the containing structure or union, keeping their
structure or union layout. This applies recursively if the containing
structure or union is also anonymous."

The phrase "keeping their structure or union layout" was added in the
C23 drafts based on DR 499, but I think it reflects what the intent
always was.

6.7.9 (Initialization) p9 says:
"Except where explicitly stated otherwise, for the purposes of this
subclause unnamed members of objects of structure and union type do not
participate in initialization. Unnamed members of structure objects
have indeterminate value even after initialization."

The only other explicit reference to "unnamed members" in 6.7.9 is in
p13. It relates to initialization of a structure or union using "a
single expression that has compatible structure or union type" (rather
than a brace-enclosed initializer list). There is no explicit
discussion of initializing anonymous structures or unions.

Based on this, it seems that an anonymous structure or union should not
participate as such in the initialization of the containing structure
or union using a brace-enclosed initializer list. But presumably the
individual members of the anonymous structure or union do participate,
since they "are considered to be members of the containing structure or
union".

It seems to follow from this that there may not be a brace-enclosed
initializer list corresponding to the anonymous structure or union.

I think it also follows that when using a brace-enclosed initializer
list with no designations, the members of an anonymous union within a
structure should follow the rules for structure initialization as given
in 6.7.9 p17 (all [named] structure members are initialized in
declaration order). Similarly, the members of an anonymous structure
within a union would follow the rules for union initialization (only
the first named member of the union is initialized).

Thus, the below code would behave as indicated:

struct S {
union {
int a;
long b;
};
int c;
};

union U {
struct {
int x;
long y;
};
int z;
};

struct S s1 = {1,2,3}; // valid, like "= {.a=1, .b=2, .c=3}"
struct S s2 = {1,2}; // valid, like "= {.a=1, .b=2, .c=0}"
struct S s3 = {{{1}},2}; // invalid (too many levels of braces)

union U u1 = {1}; // valid, like "= {.x=1}"
union U u2 = {1,2}; // invalid (too many initializers for u2)
union U u3 = {{1,2}}; // invalid (too many initializers for u3.x)

But at least GCC and Clang behave differently than this (when run with
-std=c17 -pedantic-errors, which should make them standard-conforming).
They give an "excess elements in struct initializer" error for the
declaration of s1 and accept the other declarations (with a "braces
around scalar initializer" warning for the declaration of s3). They
also treat the declaration of s2 differently, setting s2.a to 1 and
s2.c to 2.

In general, GCC and Clang seem to be acting like an anonymous structure
or union participates in initialization as a structure or union, even
though it is unnamed. This would be a reasonable thing to do in the
abstract, but I don't see how it agrees with the wording in the
standard. Am I missing something, or do GCC and Clang get this wrong?

--
Stephen Heumann

Tim Rentsch

unread,
Oct 19, 2021, 10:39:29 AM10/19/21
to
Stephen Heumann <stephen...@gmail.com> writes:

> I'm trying to figure out how initialization of anonymous
> structures and unions is supposed to work, particularly when
> using brace-enclosed initializer lists without designators.
> [..elaboration..]
>
> In general, GCC and Clang seem to be acting like an anonymous
> structure or union participates in initialization as a structure
> or union, even though it is unnamed. This would be a reasonable
> thing to do in the abstract, but I don't see how it agrees with
> the wording in the standard. Am I missing something, or do GCC
> and Clang get this wrong?

Short answer: I think what clang and gcc are doing is right.

Slightly longer answer: I can see how the wording used in the C
standard could be read in the way that clang and gcc behave. I
agree that other readings are plausible, and that at the very
least clarification is needed, and probably re-writing. What
clang and gcc do doesn't surprise me; on the contrary it's what
I would expect if your comments hadn't drawn my attention to the
question. If your goal is to understand the rules I think there
isn't any more to say. If your goal is to understand how the
rules follow from the wording, I think the question needs to be
put to the WG14 committee, perhaps in the form of a DR or change
request or whatever it is those are called these days.

Hope this helps, and good luck.
0 new messages