C vs C ++中的结构标记

时间:2016-11-13 18:18:07

标签: c++ c struct language-lawyer

我写了以下简单程序&在gcc编译器上编译它

#include <stdio.h>
typedef int i;
void foo()
{
    struct i {i i;} i;
    i.i = 3;
    printf("%i\n", i.i);
}
int main() { foo(); }

它编译&amp;在C中运行正常。(参见现场演示here)但它在C ++编译失败。 C ++编译器提供以下错误消息。

prog.cc: In function 'void foo()':
prog.cc:5:17: error: field 'i' has incomplete type 'foo()::i'
     struct i {i i;} i;
                 ^
prog.cc:5:12: note: definition of 'struct foo()::i' is not complete until the closing brace
     struct i {i i;} i;

查看实时演示here

我无法在C&amp; C ++标准。为什么它在C中编译好但在C ++中编译不好?标准对此有何看法?我非常清楚C&amp; C ++是具有不同规则的不同语言,但我很想知道确切的规则。

1 个答案:

答案 0 :(得分:20)

C和C ++之间的区别如下。在C中,数据成员i被视为具有int类型,因为如果您希望它具有类型struct i,那么您必须编写struct i i来指定关键字structi之前。

与其他变量的命名空间相比,结构标记位于各自的命名空间中。

根据C标准(6.2.3标识符的名称空间)

  

1如果可以看到多个特定标识符的声明   在翻译单元的任何一点,句法语境   消除引用不同实体的用法。 因此,有   各种标识符的单独名称空间,如   如下:

     

- 标签名称(通过标签声明的语法消除歧义   并使用);

     

- 结构,联合和枚举的标记(消除歧义   关注关键字struct,union或enum)的任何32);

     

- 结构或工会的成员;每个结构或联合都有一个   为其成员分隔名称空间(根据类型的歧义消除歧义)   用于通过访问成员的表达式。或 - &gt;操作者);

     

- 所有其他标识符,称为普通标识符(在   普通的声明符或作为枚举常量)。

对于C ++,然后在结构定义中,结构的名称隐藏了typedef的名称,编译器发出错误。在C ++中,有单独的类范围

例如在C ++(3.4名称查找)中有写

  

3 还考虑了类(第9条)的注入类名   为名称隐藏和目的而成为该类的成员   查找

和(3.4.1非限定名称查找)

  

7在成员之外定义类X的名称   函数体或嵌套类的定义29应在其中一个中声明   通过以下方式: - 在X类中使用之前或成为其成员   基类X(10.2),或......

因此,类的注入名称会在类定义中隐藏typedef名称。

考虑到在类定义之外,类的名称可以用对象的同名隐藏。因此,如果要在该范围内声明类的对象,则必须使用其精心设计的名称,如

int i;

struct i {};

//...

struct i obj;