Are "anonymous structs" standard? And, really, what *are* they?

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.

  • 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 (ie "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 struct y type"). This was likely the root of your initial confusion.


    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;
    

    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.

    链接地址: http://www.djcxy.com/p/90828.html

    上一篇: C ++ 11类型特征来区分枚举类和常规枚举

    下一篇: “匿名结构”是标准吗? 而且,真的,他们是什么?