"匿名结构"标准吗?而且,真的,他们是什么?

Lig*_*ica 55 c++

MSDN 认为匿名结构在C++中是非标准的:

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

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

@ K-ballo同意.

我被告知这个功能不一定只是创建一个未命名的结构,但我不能看到标准措辞的区别.

C++ 11说:

[C++11: 9/1]:[..]一个类说明符,类头省略了class-head-name,定义了一个未命名的类.

并为缺少名称的类型定义提供完整的语法结构.

C++ 03缺少这种明确的措辞,但同样表明identifier类型定义中的类型是可选的,并在9.4.2/5和中引用了"未命名的类" 3.5/4.

  • 那么MSDN是错的,这些东西都是完全标准的吗?
  • 或者在"未命名的结构/类"之间是否存在一些微妙之处,并且当用作成员时它们会被这个C++ 03/C++ 11功能覆盖?
  • 我错过了"unnamed struct"和"anonymous struct"之间的一些根本区别吗?它们看起来像我的同义词.

Lig*_*ica 57

所有标准文本都指创建一个"未命名的结构":

struct {
   int hi;
   int bye;
};
Run Code Online (Sandbox Code Playgroud)

只是一个友好的友好类型,没有可访问的名称.

以标准方式,它可以实例化为这样的成员:

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

int main()
{
   Foo f;
   f.bar.hi = 3;
}
Run Code Online (Sandbox Code Playgroud)

但是"匿名结构"略有不同 - 它是"未命名的结构"的组合,以及您在父对象中神奇地从其中获取成员的事实:

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

int main()
{
   Foo f;
   f.hi = 3;
}
Run Code Online (Sandbox Code Playgroud)

与直觉相反,这不只是创建一个嵌套的未命名结构Foo,而且还会自动为您提供各种"匿名成员",使成员可以在父对象中访问.

这个功能是非标准的.GCC 确实支持它,Visual C++也是如此.Windows API标头默认使用此功能,但您可以#define NONAMELESSUNION在包含Windows标头文件之前通过添加来指定您不希望它.

与"匿名工会" 的标准功能相比,它们执行类似的操作:

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

int main()
{
   Foo f;
   f.hi = 3;
}
Run Code Online (Sandbox Code Playgroud)

看起来虽然术语"未命名"指的是类型(即"类"或"结构")本身,但术语"匿名"指的是实际的实例化成员(使用"结构"的旧含义) "那更接近"某种struct类型的对象").这可能是您最初混淆的根源.

  • @vsz:匿名结构可用于别名struct成员.考虑这一点类型:`struct Point3 {union {struct {float x,y,z; }; float arr [3]; }; }; Point3 pt; pt.x = 3; pt.arr [0] == 3; //匿名结构允许这个`便利性是优点 (4认同)
  • BTW,匿名结构的主要用途是在一个联合内部,因为它允许联合的变体具有多个相邻的字段,而没有额外的命名级别.例如`union {double as_d; struct {uint32_t as_u32a,as_u32b}; ` - 所以现在所有的`as_d`,`as_u32a`,`as_u32b`都在同一个空间,但是'as_u32b`在不同的地址.我见过旧的C代码,人们使用#define来隐藏这些构造中需要的丑陋名称,如`rec.u.pcktA.hdr`,在此功能可用之前. (4认同)
  • 那个'NONAMELESSUNION` /`NONAMELESSSTRUCT`对我来说是新闻,它不是在_Platform SDK_中的几个版本...顺便说一下,你是在和自己说话,好像你是一个不同的人在那里的最后一句话你的笔记? (2认同)
  • 与将'hi`和`bye`直接作为`Foo`的成员相比,这有什么好处? (2认同)
  • 也许这个结构的名称不那么混乱,可能是"透明联合"和"透明"结构. (2认同)

Pet*_*ker 12

微软称之为匿名结构的东西不是标准的.未命名的结构只是一个没有名称的普通结构.除非您还定义了该类型的对象,否则您无法使用其中一个:

struct {
    int i;
    double d;
} my_object;

my_object.d = 2.3;
Run Code Online (Sandbox Code Playgroud)

匿名工会是标准的一部分,它们具有您期望阅读Microsoft对其匿名结构的描述的行为:

union {
    int i;
    double d;
};

d = 2.3;
Run Code Online (Sandbox Code Playgroud)

  • @CiroSantilli - 微软经常让事情变得混乱. (2认同)

K-b*_*llo 9

该标准谈到了匿名工会:[9.5]/5

形式的联合

union { member-specification } ;
Run Code Online (Sandbox Code Playgroud)

被称为匿名联盟; 它定义了一个未命名类型的未命名对象.匿名联合的成员规范只应定义非静态数据成员.[注意:嵌套类型和函数不能在匿名联合中声明.-end note]匿名工会成员的名称应与宣布匿名工会的范围内的任何其他实体的名称不同.出于名称查找的目的,在匿名联合定义之后,匿名联合的成员被认为已在声明匿名联合的范围中定义.[例如:

void f() {
    union { int a; const char* p; };
    a = 1;
    p = "Jennifer";
}
Run Code Online (Sandbox Code Playgroud)

这里a和p像普通(非成员)变量一样使用,但由于它们是联合成员,因此它们具有相同的地址. - 末端的例子]

匿名结构微软谈论是此功能unions,但应用到structs.不仅仅是一个未命名的定义,重要的是要注意匿名union/struct的标准被认为是在声明匿名union/struct的范围内定义的.

据我所知,标准中没有未命名结构的行为.请注意,在引用的示例中,您可以实现无法实现的功能,例如共享堆栈中变量的存储,而匿名结构不会给表带来任何新内容.

  • 嗯好的,那样看着它.他们在量子世界中共享存储和地址,但牛顿力学会认为他们不能共享存储和地址,因为在任何给定时间只有一个占用! (2认同)