为啥 typedef 的名称可以用作结构成员的名称?

Posted

技术标签:

【中文标题】为啥 typedef 的名称可以用作结构成员的名称?【英文标题】:Why can typedef'd names be used as the names of struct members?为什么 typedef 的名称可以用作结构成员的名称? 【发布时间】:2020-08-13 16:52:27 【问题描述】:

我刚刚发现gccclang 都接受以下代码:

typedef int blah;
struct s  char blah; ;

但是,他们拒绝这样做,因为类型名称被用作标识符:

typedef int blah;
char blah;

这是否意味着 typedef 的名称在结构定义中不可见?不,因为这在 gcc 和 clang 中都有效:

typedef int blah;
struct s  blah blah; 

我正在查看 C99 标准,但找不到任何解释为什么 typedef 的名称可以用作结构成员的名称,但不能用作同一范围内的变量的名称。

有人能解释这是为什么吗?参考任何适用的标准将不胜感激。

【问题讨论】:

第一个sn-p blah是一个结构体成员名,第二个sn-p blah是一个变量名,这是两个非常不同的东西。 This question 可能会回答您自己的问题,尽管它的质量不佳。 int var; struct foo bar; bar.var = var;一样的原因 @Jabberwocky 感谢您的评论。您是否知道任何 C 标准中是否有任何内容阐明了这两个事物在相同范围内已经定义类型的名称的行为方式?我正在阅读标准,并没有看到任何表明会有任何差异的内容。 请说清楚,gcc 和 clang 接受还是拒绝? 【参考方案1】:

取自这里:https://www.spinellis.gr/cscout/doc/name.html

C 有 4 个不同的命名空间。这些不是来自 C++ 的命名空间,它们是使用关键字 namespace 访问的。相反,这些是符号的单独区域:

结构/联合/枚举的标签

struct/union 的成员(实际上为每个struct/union 分配了一个单独的命名空间)

标签

普通标识符(在 C 标准中称为对象)

【讨论】:

【参考方案2】:

结构和普通变量的成员位于不同的命名空间中。这就是为什么有两个具有相同标识符名称的普通变量会失败,而如果在结构成员中使用相同的标识符名称并且普通变量很好。

C 标准定义了不同的命名空间:

6.2.3 Name spaces of identifiers

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

标签名称(通过标签声明和使用的语法消除歧义); 结构体、联合体和枚举的标记(通过关键字struct、union 或enum 的任意32) 来消除歧义); 结构或工会的成员;每个结构或联合对其成员都有一个单独的名称空间(由 用于通过 . 访问成员的表达式。或 -> 运算符); 所有其他标识符,称为普通标识符(在普通声明符中声明或作为枚举常量声明)。

(最后两个项目符号直接解决了这个问题)

是的,typedef'ed 标识符与普通标识符共享名称空间。 6.7.8 Type definitions:

[...] typedef 名称与在普通声明器中声明的其他标识符共享相同的名称空间。

【讨论】:

谢谢!我没看过那个部分。它几乎回答了我的问题,但不完全是。缺少的是:这是否意味着使用 typedef 创建的类型名称与“所有其他标识符”共享相同的命名空间?第 4 个命名空间被描述为用于“普通声明符或枚举常量”,但 typedef 两者都不是。 @AlexD 是的,typedef 的名称与普通标识符共享命名空间(第 4 个)。用参考更新了答案。 非常感谢!

以上是关于为啥 typedef 的名称可以用作结构成员的名称?的主要内容,如果未能解决你的问题,请参考以下文章

C : typedef 结构名称 ...; VS typedef struct... 名称;

typedef 结构在链接静态库时会导致名称冲突吗?

typedef struct name 没有后续结构定义的名称

text 使用Typedef为结构数据类型提供较短的名称

名称后带有第二个说明符的 typedef 结构 [重复]

Linux C/C++关于结构体定义,typedef关键字的使用场景