“匿名结构”的标准吗?真的,它们是什么?

时间:2022-09-06 22:42:46

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

MSDN认为匿名结构体在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.

Microsoft C扩展允许您在另一个结构中声明一个结构变量,而不指定它的名称。这些嵌套结构称为匿名结构。c++不允许匿名结构。

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

您可以访问匿名结构的成员,就好像它们是包含结构中的成员一样。

@K-ballo agrees.

@K-ballo表示同意。

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说:

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

[C + + 11:9/1]:[. .类标识符的类头忽略类头名称定义一个未命名的类。

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.

c++ 03没有这种明确的措辞,但类似地表明类型定义中的标识符是可选的,并且在9.2 /5和3.5/4中引用“未命名类”。

  • So is MSDN wrong, and these things are all completely standard?
  • MSDN是错的,这些都是完全标准的吗?
  • 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?
  • 或者,在“未命名结构体/类”和作为成员使用时,我是否遗漏了一些微妙之处,使它们不能被这个c++ 03/ c++ 11功能覆盖?
  • Am I missing some fundamental difference between "unnamed struct" and "anonymous struct"? They look like synonyms to me.
  • 我是否遗漏了“未命名结构”和“匿名结构”之间的一些基本区别?我觉得它们是同义词。

3 个解决方案

#1


49  

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.

与直觉相反,这不仅仅是创建一个未命名的结构,它是嵌套的witin Foo,而且会自动给您一个“匿名成员”,使成员可以在父对象中访问。

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.

这个功能是非标准的。GCC确实支持它,Visual c++也支持它。Windows API header默认使用了这个特性,但是您可以通过在包含Windows头文件之前添加#define NONAMELESSUNION来指定不需要它。

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.

虽然“无名”一词指的是类型(例如:“类”或“结构体”)本身,术语“匿名”指的是实际实例化的成员(使用“结构体”的旧含义,更接近“某种结构类型的对象”)。这可能是你最初困惑的根源。

#2


11  

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;

#3


9  

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

标准讨论匿名联盟:[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 ]

在这里,a和p像普通的(非成员)变量一样使用,但是由于它们是联合成员,所以它们有相同的地址。端例子)

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.

微软谈论的匿名结构体是工会的这一特性,但应用于结构体。不只是一个未命名的定义,重要的是要注意匿名union/struct的成员被认为是在声明匿名union/struct的范围中定义的。

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.

据我所知,标准中没有未命名结构体的行为。请注意,在上述示例中,您可以实现一些其他情况下不可能实现的功能,比如共享堆栈中的变量存储,而匿名结构不会为表带来任何新的内容。

#1


49  

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.

与直觉相反,这不仅仅是创建一个未命名的结构,它是嵌套的witin Foo,而且会自动给您一个“匿名成员”,使成员可以在父对象中访问。

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.

这个功能是非标准的。GCC确实支持它,Visual c++也支持它。Windows API header默认使用了这个特性,但是您可以通过在包含Windows头文件之前添加#define NONAMELESSUNION来指定不需要它。

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.

虽然“无名”一词指的是类型(例如:“类”或“结构体”)本身,术语“匿名”指的是实际实例化的成员(使用“结构体”的旧含义,更接近“某种结构类型的对象”)。这可能是你最初困惑的根源。

#2


11  

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;

#3


9  

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

标准讨论匿名联盟:[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 ]

在这里,a和p像普通的(非成员)变量一样使用,但是由于它们是联合成员,所以它们有相同的地址。端例子)

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.

微软谈论的匿名结构体是工会的这一特性,但应用于结构体。不只是一个未命名的定义,重要的是要注意匿名union/struct的成员被认为是在声明匿名union/struct的范围中定义的。

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.

据我所知,标准中没有未命名结构体的行为。请注意,在上述示例中,您可以实现一些其他情况下不可能实现的功能,比如共享堆栈中的变量存储,而匿名结构不会为表带来任何新的内容。