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

Why can typedef'd names be used as the names of struct members?

我刚刚发现 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 的名称可以用作结构成员的名称,但不能用作同一范围内的变量的名称。

有人可以解释这是为什么吗?如果能参考任何适用的标准,我们将不胜感激。

取自此处:https://www.spinellis.gr/cscout/doc/name.html

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

  • struct/union/enum

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

  • 标签

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

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

C 标准定义了不同的名称spaces:

6.2.3 Name spaces of identifiers

If more than one declaration of a particular identifier is visible at any point in a translation unit, the syntactic context disambiguates uses that refer to different entities. Thus, there are separate name spaces for various categories of identifiers, as follows:

  • label names (disambiguated by the syntax of the label declaration and use);
  • the tags of structures, unions, and enumerations (disambiguated by following any32) of the keywords struct, union, or enum);
  • the members of structures or unions; each structure or union has a separate name space for its members (disambiguated by the type of the expression used to access the member via the . or -> operator);
  • all other identifiers, called ordinary identifiers (declared in ordinary declarators or as enumeration constants).

(最后两项直接解决这个问题)

是的,typedefed 标识符与普通标识符共享名称 space。 6.7.8 Type definitions:

[...] A typedef name shares the same name space as other identifiers declared in ordinary declarators.