62

MSDN reckons that anonymous structs are non-standard in C++:

A Microsoft C extension allows you to declare a structure variable within another structure without giving it a name. These nested structures are called anonymous structures. C++ does not allow anonymous structures.

You can access the members of an anonymous structure as if they were members in the containing structure.

@K-ballo agrees.

I'm told that this feature isn't necessarily the same as just creating an unnamed struct but I can't see a distinction in terms of standard wording.

C++11 says:

[C++11: 9/1]: [..] A class-specifier whose class-head omits the class-head-name defines an unnamed class.

and provides an entire grammatical construction for a type definition missing a name.

C++03 lacks this explicit wording, but similarly indicates that the identifier in a type definition is optional, and makes reference to "unnamed classes" in 9.4.2/5 and 3.5/4.

  • So is MSDN wrong, and these things are all completely standard?
  • Or is there some subtlety I'm missing between "unnamed structs/classes" and the same when used as members that prevents them from being covered by this C++03/C++11 functionality?
  • Am I missing some fundamental difference between "unnamed struct" and "anonymous struct"? They look like synonyms to me.
Community
  • 1
  • 1
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • Yey I'm cited in your question! That's my knowledge with _C++03_, don't find anything that says it changed on _C++11_... – K-ballo Jan 09 '13 at 23:04
  • 1
    @K-ballo: BTW did you get a notification for that? – Lightness Races in Orbit Jan 09 '13 at 23:06
  • Sounds like two different things. In the case you refer to, there are structs which aren't instantiated with names, but rather like what's ok with unions. "anonymous structs" however, I interpret as structs with an anonymous type name. Such as: `struct { int x; } y;` which is fine. Am I missing something? – gustaf r Jan 09 '13 at 23:06
  • @K-ballo I don't think it changed either, In fact, I only find the *mention* of the word "anonymous" on 11 of the 1300+ pages of the standard, and each of those (including appearance in the index) are directly related to *unions*. – WhozCraig Jan 09 '13 at 23:08
  • @gustafr The example you're showing is an unnamed struct, and is supported. An anonymous struct would not have the variable `y`. – WhozCraig Jan 09 '13 at 23:10
  • 4
    @WhozCraig, got it, thanks! So *unnamed != anonymous* nowadays. Excellent. – gustaf r Jan 09 '13 at 23:13
  • @gustafr: Looks like that's the crux of it, yeah. – Lightness Races in Orbit Jan 09 '13 at 23:14
  • @LightnessRacesinOrbit: I'd say that particular page of the MSDN deserves an apology... and that can't be said about many of them :P (not a downvote related comment) – K-ballo Jan 09 '13 at 23:19
  • @K-ballo: Looks like it's going to get one by virtue of this page existing, yeah. It probably wouldn't have hurt them to include a proper explanation like that found in my answer, though, y'know! – Lightness Races in Orbit Jan 09 '13 at 23:20

3 Answers3

66

All the standard text refers to creating an "unnamed struct":

struct {
   int hi;
   int bye;
};

Just a nice friendly type, with no accessible name.

In a standard way, it could be instantiated as a member like this:

struct Foo {
   struct {
      int hi;
      int bye;
   } bar;
};

int main()
{
   Foo f;
   f.bar.hi = 3;
}

But an "anonymous struct" is subtly different — it's the combination of an "unnamed struct" and the fact that you magically get members out of it in the parent object:

struct Foo {
   struct {
      int hi;
      int bye;
   }; // <--- no member name!
};

int main()
{
   Foo f;
   f.hi = 3;
}

Converse to intuition, this does not merely create an unnamed struct that's nested witin Foo, but also automatically gives you an "anonymous member" of sorts which makes the members accessible within the parent object.

It is this functionality that is non-standard. GCC does support it, and so does Visual C++. Windows API headers make use of this feature by default, but you can specify that you don't want it by adding #define NONAMELESSUNION before including the Windows header files.

Compare with the standard functionality of "anonymous unions" which do a similar thing:

struct Foo {
   union {
      int hi;
      int bye;
   }; // <--- no member name!
};

int main()
{
   Foo f;
   f.hi = 3;
}

It appears that, though the term "unnamed" refers to the type (i.e. "the class" or "the struct") itself, the term "anonymous" refers instead to the actual instantiated member (using an older meaning of "the struct" that's closer to "an object of some structy type"). This was likely the root of your initial confusion.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • Microsoft uses these things in several places in the Windows headers, so any compiler that supports Windows has to also support anonymous structs. – Pete Becker Jan 09 '13 at 23:10
  • Its my understanding that GCC did quite some work to support anonymous structs as well... – K-ballo Jan 09 '13 at 23:10
  • @MooingDuck: Like that? :) – Lightness Races in Orbit Jan 09 '13 at 23:11
  • Yeah, that's more or less what I was thinking. – Mooing Duck Jan 09 '13 at 23:13
  • 2
    That `NONAMELESSUNION`/`NONAMELESSSTRUCT` bit is news to me, it wasn't in the _Platform SDK_ a few versions back... btw, are you talking to yourself as if you were a different person there on the very last sentence of your note? – K-ballo Jan 09 '13 at 23:51
  • @K-ballo: It seems to be an "undocumented feature" from what I can tell, though the relevant logic can be found in windef.h and goes back to 1996 at the latest. – Lightness Races in Orbit Jan 10 '13 at 01:44
  • 2
    What are the advantages of this compared to just having `hi` and `bye` directly as members of `Foo` ? – vsz Jan 10 '13 at 06:03
  • 4
    @vsz: anonymous structs can be used to alias struct members. Consider this point type: `struct Point3 { union { struct { float x,y,z; }; float arr[3]; }; }; Point3 pt; pt.x = 3; pt.arr[0] == 3; // anonymous struct allows this` Convenience is the advantage – Dwighte Jul 23 '14 at 22:03
  • 2
    Perhaps a less confusing name for this construct would be 'transparent union' and 'transparent' struct. – greggo Apr 06 '17 at 17:14
  • 4
    BTW, a prime use for anonymous structs is inside a union, since it allows a variant of the union to have multiple adjacent fields without having an extra level of naming. e.g. `union { double as_d; struct { uint32_t as_u32a, as_u32b}; };` - so now all of `as_d`, `as_u32a`, `as_u32b` are in the same space, but `as_u32b` is at a different address. I've seen old C code where people used #define to hide the ugly names like `rec.u.pcktA.hdr` which were needed in such constructs, before this feature was available. – greggo Apr 06 '17 at 17:23
14

The things that Microsoft calls anonymous structs are not standard. An unnamed struct is just an ordinary struct that doesn't have a name. There's not much you can do with one, unless you also define an object of that type:

struct {
    int i;
    double d;
} my_object;

my_object.d = 2.3;

Anonymous unions are part of the standard, and they have the behavior you'd expect from reading Microsoft's description of their anonymous structs:

union {
    int i;
    double d;
};

d = 2.3;
Pete Becker
  • 74,985
  • 8
  • 76
  • 165
  • 1
    This answer conflicts with @Lighness's which makes a difference between anonymous and unnamed. I think he is correct, since Anonymous structs were introduced in C11, but `struct { int a; } s;` is possible since C89. – Ciro Santilli OurBigBook.com Sep 18 '14 at 11:36
  • 1
    @CiroSantilli - the question is about what **Microsoft** calls anonymous structs, not what any of the C standards call anonymous structs. I've edited the answer to emphasize that. – Pete Becker Sep 18 '14 at 11:41
  • 2
    @CiroSantilli - Microsoft often makes things confusing. – Pete Becker Sep 18 '14 at 11:46
9

The standard talks about anonymous unions: [9.5]/5

A union of the form

union { member-specification } ;

is called an anonymous union; it defines an unnamed object of unnamed type. The member-specification of an anonymous union shall only define non-static data members. [ Note: Nested types and functions cannot be declared within an anonymous union. —end note ] The names of the members of an anonymous union shall be distinct from the names of any other entity in the scope in which the anonymous union is declared. 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. [ Example:

void f() {
    union { int a; const char* p; };
    a = 1;
    p = "Jennifer";
}

Here a and p are used like ordinary (nonmember) variables, but since they are union members they have the same address. —end example ]

The anonymous structs that Microsoft talks about is this feature for unions but applied to structs. Is not just an unnamed definition, its important to note that mebers of the anonymous union/struct are considered to have been defined in the scope in which the anonymous union/struct is declared.

As far as I know, there is no such behavior for unnamed structs in the Standard. Note how in the cited example you can achieve things that wouldn't be otherwise possible, like sharing storage for variables in the stack, while anonymous structs bring nothing new to the table.

K-ballo
  • 80,396
  • 20
  • 159
  • 169
  • Strictly speaking `union` doesn't let you "share" anything, since only one member may be "active" at a time. I suppose calling it a single-occupancy _time share_ would be acceptable :P – Lightness Races in Orbit Jan 09 '13 at 23:20
  • @LightnessRacesinOrbit: They do share _storage_ and _address_, don't they? But I see your point... – K-ballo Jan 09 '13 at 23:20
  • 2
    Mmm okay looking at it that way. They share storage and address in the quantum world, but Newtonian mechanics would contend that they can't share storage and address because only one takes up either at any given time! – Lightness Races in Orbit Jan 09 '13 at 23:22
  • @LightnessRacesinOrbit: That would be a perfect analogy! – K-ballo Jan 09 '13 at 23:22
  • 1
    Re: your last sentance, The callout for unnamed structs *verbatim* is not in the standard, but unnamed *classes* are covered in 9p1. With that, the grammar specifically defines the declaration of a "class key", which can be `struct` `class`, or `union`, and all of them are covered as being supported as unnamed. Specifically, "A class-specifier whose class-head omits the class-head-name defines an unnamed class.", where "class specifier" leads to any of the three "class-key"s as the head preamble. (and +1, btw) – WhozCraig Jan 09 '13 at 23:24
  • @WhozCraig: Yeah, that was kind of the prelude to this question being raised... _unnamed vs. anonymous_ – K-ballo Jan 09 '13 at 23:26
  • @K-ballo LOL. I'm a little slow on the uptake today, but thats finally starting to sink in on me =P – WhozCraig Jan 09 '13 at 23:28
  • @WhozCraig: I think he really did mean "no such behavior[sic] **for**" and not "no such behavior[sic] **as**" :) – Lightness Races in Orbit Jan 09 '13 at 23:28
  • @LightnessRacesinOrbit thanks for the clarification (and K-ballo as well). It didn't ring right in my head the first time I saw it. Its clear what was meant now. – WhozCraig Jan 09 '13 at 23:32