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

时间:2013-01-09 23:01:50

标签: c++

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

  

Microsoft C扩展允许您声明结构变量   在另一个结构中没有给它起名字。这些嵌套   结构称为匿名结构。 C ++不允许   匿名结构。

     

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

@K-ballo agrees

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

C ++ 11说:

  

[C++11: 9/1] [..] class-specifier ,其 class-head 省略了 class-head -name 定义一个未命名的类。

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

C ++ 03缺少这种明确的措辞,但同样表明类型定义中的identifier是可选的,并引用9.4.2/53.5/4中的“未命名类”。

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

3 个答案:

答案 0 :(得分:57)

所有标准文本都是指创建“未命名的结构”:

struct {
   int hi;
   int bye;
};

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

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

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

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

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

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

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

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

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

与“匿名工会”的标准功能进行比较,这些功能做了类似的事情:

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

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

看来,虽然术语“未命名”指的是类型(即“类”或“结构”)本身,但术语“匿名”指的是实际的实例化成员(使用更接近“某个struct y类型的对象”的旧结构“结构”)。这可能是你最初混淆的根源。

答案 1 :(得分:12)

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

struct {
    int i;
    double d;
} my_object;

my_object.d = 2.3;

匿名工会是该标准的一部分,他们有阅读{匿名结构Microsoft's description所期望的行为:

union {
    int i;
    double d;
};

d = 2.3;

答案 2 :(得分:9)

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

  

表格

的联合
union { member-specification } ;
     

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

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

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

Microsoft 所讨论的匿名结构unions的此功能,但已应用于structs。不仅仅是一个未命名的定义,重要的是要注意匿名union / struct的标准被认为是在声明匿名union / struct的范围内定义的。

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