Anonymous structures in C and C++

1,130 views
Skip to first unread message

Vlad from Moscow

unread,
Nov 29, 2016, 4:09:30 PM11/29/16
to ISO C++ Standard - Discussion
I run the following C++ code at www.idepne.com using the C++14 mode of the compiler

#include <iostream>
struct
{
 
int x, y;
 
struct { int a, b; };
} p;
int main()
{
 p
.a = 10;
 
 
return 0;
}


and it compiles successfully. However when I run a similar code using the C99strict mode

#include <stdio.h>
struct
{
 
int x, y;
 
struct { int a, b; };
} p;
int main(void)
{
 p
.a = 10;
 
return 0;
}


then I got the following diagnostic message

prog.c:6:22: error: ISO C99 doesn't support unnamed structs/unions [-Werror=pedantic]
  struct { int a, b; };
                      ^


Thus I wonder did I miss the day when the C++ Standard adopted anonymous structures in C++ or is it a own language extension of the compiler?

And did C99 have anonymous structures or were they adopted only in the C 2011?




Richard Smith

unread,
Nov 29, 2016, 6:06:22 PM11/29/16
to std-dis...@isocpp.org
On 29 November 2016 at 13:09, 'Vlad from Moscow' via ISO C++ Standard - Discussion <std-dis...@isocpp.org> wrote:
I run the following C++ code at www.idepne.com using the C++14 mode of the compiler

#include <iostream>
struct
{
 
int x, y;
 
struct { int a, b; };
} p;
int main()
{
 p
.a = 10;
 
 
return 0;
}


and it compiles successfully. However when I run a similar code using the C99strict mode

#include <stdio.h>
struct
{
 
int x, y;
 
struct { int a, b; };
} p;
int main(void)
{
 p
.a = 10;
 
return 0;
}


then I got the following diagnostic message

prog.c:6:22: error: ISO C99 doesn't support unnamed structs/unions [-Werror=pedantic]
  struct { int a, b; };
                      ^


Thus I wonder did I miss the day when the C++ Standard adopted anonymous structures in C++ or is it a own language extension of the compiler?

It's an extension. C++ bans this in [class.mem]/2: "[...]  each such member-declaration shall either declare at least one member name of the class or declare at least one unnamed bit-field."

Anonymous unions are permitted in C++, since by [class.union.anon]/1,

  struct A {
    union { int x, y; };
  };

... declares x and y to be member names of A.

And did C99 have anonymous structures or were they adopted only in the C 2011?

They were added in C11. C99 6.7/2 bans them: "A declaration shall declare at least a declarator (other than the parameters of a function or the members of a structure or union), a tag, or the members of an enumeration."

Vlad from Moscow

unread,
Nov 29, 2016, 6:33:39 PM11/29/16
to ISO C++ Standard - Discussion


среда, 30 ноября 2016 г., 2:06:22 UTC+3 пользователь Richard Smith написал:
However in fact the same is written in the N1548 Committee Draft — December 2, 2010 where anonymous structures and unions are present

2 Adeclaration other than a static_assert declaration shall declare at least a declarator

Richard Smith

unread,
Nov 29, 2016, 6:58:38 PM11/29/16
to std-dis...@isocpp.org
Ah right, sorry, it's been a while since I've stared at this part of the C standard. The contents of a struct in C are struct-declarations, not declarations, so that rule doesn't apply. This was previously enforced by the grammar; C99 has:

  struct-declaration:
      specifier-qualifier-list struct-declarator-list ;

(note that the declarator list is mandatory), whereas C11 has:

  struct-declaration:
      specifier-qualifier-list struct-declarator-listopt ;
      static_assert-declaration

Vlad from Moscow

unread,
Nov 29, 2016, 7:11:57 PM11/29/16
to ISO C++ Standard - Discussion


среда, 30 ноября 2016 г., 2:58:38 UTC+3 пользователь Richard Smith написал:
So you can confirm that there was not such a term as anonymous structure in C99 can you? Is the anonymous union also absent in the C99 Standard? Unfortunately I myself have no at hand the C99 Standard.
 

Victor Dyachenko

unread,
Nov 30, 2016, 5:03:56 AM11/30/16
to ISO C++ Standard - Discussion

 https://gcc.gnu.org/wiki/C11Status

"Anonymous struct and union"

Belloc

unread,
Nov 30, 2016, 3:00:37 PM11/30/16
to ISO C++ Standard - Discussion

On Tuesday, November 29, 2016 at 9:06:22 PM UTC-2, Richard Smith wrote:

It's an extension. C++ bans this in [class.mem]/2: "[...]  each such member-declaration shall either declare at least one
member name of the class or declare at least one unnamed bit-field."

Anonymous unions are permitted in C++, since by [class.union.anon]/1,

  struct A {
    union { int x, y; };
  };

... declares x and y to be member names of A.

I fail to see in [class.union.anon] any reference to the fact that an anonymous union can be a data-member of a class,
or that a non-static data-member of an anonymous union is a data-member of the class containing this anonymous union,
other than a few tangential references on this respect, in paragraphs 2 and 4,as follows:

§2:

A storage class is not allowed in a declaration of an anonymous union in a class scope.

§4 (emphasis is mine):

A union-like class is a union or a class that has an anonymous union as a direct member. A union-like class X
has a set of variant members. If X is a union, a non-static data member of X that is not an anonymous union
is a variant member of X. In addition, a non-static data member of an anonymous union that is a member of X
is also a variant member of X.

Note also that the definition of an anonymous union in [class.union.anon]/1 is not in the C++ grammar, and more, the
definition of a member-declaration in [class.mem] seems to exclude an anonymous union from being contemplated by this definition.

Richard Smith

unread,
Nov 30, 2016, 3:56:02 PM11/30/16
to std-dis...@isocpp.org
On 30 November 2016 at 12:00, Belloc <jabe...@gmail.com> wrote:

On Tuesday, November 29, 2016 at 9:06:22 PM UTC-2, Richard Smith wrote:

It's an extension. C++ bans this in [class.mem]/2: "[...]  each such member-declaration shall either declare at least one
member name of the class or declare at least one unnamed bit-field."

Anonymous unions are permitted in C++, since by [class.union.anon]/1,

  struct A {
    union { int x, y; };
  };

... declares x and y to be member names of A.

I fail to see in [class.union.anon] any reference to the fact that an anonymous union can be a data-member of a class,

The "unnamed object of unnamed type" wording there is unfortunately not very precise. What this means is that

  union { member-specification };

is equivalent to

  union { member-specification } unique ;

(except that the member names declared in the member-specification are also introduced as names in the enclosing scope). Inside a class, this declares a data member, outside a class it declares a variable.

or that a non-static data-member of an anonymous union is a data-member of the class containing this anonymous union,

It's not, but it is a member name of the enclosing class, because "For the purpose of name lookup, after the anonymous union definition, the members of the anonymous union are considered to have been defined in the scope in which the anonymous union is declared." (Again, this could be more clearly stated.)
 
other than a few tangential references on this respect, in paragraphs 2 and 4,as follows:

§2:

A storage class is not allowed in a declaration of an anonymous union in a class scope.

§4 (emphasis is mine):

A union-like class is a union or a class that has an anonymous union as a direct member. A union-like class X
has a set of variant members. If X is a union, a non-static data member of X that is not an anonymous union
is a variant member of X. In addition, a non-static data member of an anonymous union that is a member of X
is also a variant member of X.

Note also that the definition of an anonymous union in [class.union.anon]/1 is not in the C++ grammar, and more, the
definition of a member-declaration in [class.mem] seems to exclude an anonymous union from being contemplated by this definition.

It does match the grammar: one form of member-declaration is:

  attribute-specifier-seqopt decl-specifier-seqopt member-declarator-listopt ;

Note that all parts of this are optional, and in particular the form

  decl-specifier-seqopt ;

... matches that production.

    union { member-specification }

is a class-specifier, which is a form of defining-type-specifier, which is a form of decl-specifier, so it is a member-declaration.

Myriachan

unread,
Nov 30, 2016, 5:52:27 PM11/30/16
to ISO C++ Standard - Discussion

On Wednesday, November 30, 2016 at 12:56:02 PM UTC-8, Richard Smith wrote:
On 30 November 2016 at 12:00, Belloc <jabe...@gmail.com> wrote:

On Tuesday, November 29, 2016 at 9:06:22 PM UTC-2, Richard Smith wrote:

It's an extension. C++ bans this in [class.mem]/2: "[...]  each such member-declaration shall either declare at least one
member name of the class or declare at least one unnamed bit-field."



Is there a reason that C++ doesn't allow anonymous structs?  GCC, Clang, MSVC and ICC all do, outside of pedantic modes, and probably others as well.  These compilers also permit the class-key "class" instead of "struct", though you'd obviously need to use "public:".

GCC and Clang throw an error if you try to have a non-union class at namespace or function scope: they have to be a class member.  ICC and MSVC treat such an attempt as a useless unnamed declaration.

I suppose that an anonymous struct at namespace or function scope, or within a non-union class, could be permissible; the only real use of such a device would be to force the compiler to allocate variables in a particular order in memory without having to always use member access syntax.  A niche case, to be sure.  The ordinary case of an anonymous struct within a union is far more useful.  (An anonymous struct within a struct would only affect member alignment, as far as I can tell.)

Melissa
Reply all
Reply to author
Forward
0 new messages