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)