【问题标题】:structure tag in C vs C++C 与 C++ 中的结构标记
【发布时间】:2017-03-27 09:47:01
【问题描述】:

我编写了以下简单程序并在 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(); }

它在 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 和 C++ 标准中找不到与此相关的规则。为什么它在 C 中编译得很好,但在 C++ 中编译得不好?标准对此有何规定?我非常清楚 C 和 C++ 是具有不同规则的不同语言,但我很想知道确切的规则。

【问题讨论】:

  • 我想问题在于,在 C 中,您的结构名称是 struct i,因此您的结构中的 i 明确具有 typedef int i; 的类型,即 int,但在 C++ 中structs name 只是i 所以你的structs name 阴影(阴影甚至发生在typenames 上?)typedef 和你的struct 包含它自己。
  • 如果你的风格是这样的,要拥有同名的变量、类型和结构,我建议你参加International Obfuscated C Code Contest。否则这将不是问题。
  • 你的程序听起来像说我的骑士。“我!我!我!”

标签: c++ c struct language-lawyer


【解决方案1】:

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

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

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

1 如果一个特定标识符的多个声明可见 在翻译单元的任何一点,句法上下文 消除引用不同实体的用法的歧义。 因此,有 不同类别标识符的单独名称空间,如 如下:

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

——结构、联合和枚举的标签(通过 在关键字 struct、union 或 enum 中的 any32) 之后);

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

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

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

例如在 C++ (3.4 Name lookup) 中有这样写的

3 类的注入类名(第 9 条)也被考虑 为了名称隐藏和 查找

和(3.4.1 不合格名称查找)

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

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

考虑到在类定义之外,类的名称可以被对象的相同名称隐藏。因此,如果您想在该范围内声明该类的对象,则必须使用其详细名称,例如

int i;

struct i {};

//...

struct i obj;

【讨论】:

    猜你喜欢
    • 2012-07-28
    • 1970-01-01
    • 2011-07-18
    • 1970-01-01
    • 2014-06-21
    • 2023-03-09
    • 2011-02-14
    • 2012-10-02
    • 2016-02-23
    相关资源
    最近更新 更多