C vs C++中的结构标记

Des*_*tor 18 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(); }
Run Code Online (Sandbox Code Playgroud)

它在C中编译并运行良好.(请参见此处的实时演示)但它在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;
Run Code Online (Sandbox Code Playgroud)

在这里查看现场演示

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

Vla*_*cow 20

C和C++之间的区别如下.在C语言中的数据成员i被认为具有类型int,因为如果你想它有型struct i,那么你必须写struct i i指定关键字struct之前i.

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

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

1如果在翻译单元中的任何一点可以看到多个特定标识符的声明,则语法上下文消除了引用不同实体的用法的歧义.因此,各种标识符类别都有单独的名称空间,如下所示:

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

- 关键字struct,union或enum)的结构,联合和枚举的标记(通过遵循any32消除歧义);

- 结构或工会的成员; 每个结构或联合为其成员都有一个单独的名称空间(通过.或 - >运算符用于访问成员的表达式的类型消除歧义);

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

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

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

3 为了名称隐藏和查找的目的,类的注入类名(第9条)也被认为是该类的成员.

和(3.4.1不合格的名称查找)

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

因此,类的注入名称隐藏了类定义中的typedef名称.

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

int i;

struct i {};

//...

struct i obj;
Run Code Online (Sandbox Code Playgroud)