为什么可以在结构定义中使用相同的名称?
Why can you use the same name in struct definitions?
我最近发现这段代码:
struct foo { int foo; } foo;
我编译了这个代码片段(当然有一个空的 main()
函数!),并且编译时没有警告。为什么这是合法的?
C 中的名称过去是在名称空间中。
在您的示例中,名称 foo 出现在结构、结构字段和全局命名空间中。
允许这种重复情况可能是因为需要额外的计算才能找到这些命名空间之间的冲突,而计算过去非常昂贵。
从那以后,C 保持向后兼容性,因为这就是 C 所做的。
编译器可以根据它们出现的上下文来区分它们。 C 2018 6.2.3,“标识符的命名空间”说:
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 any 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).
我最近发现这段代码:
struct foo { int foo; } foo;
我编译了这个代码片段(当然有一个空的 main()
函数!),并且编译时没有警告。为什么这是合法的?
C 中的名称过去是在名称空间中。
在您的示例中,名称 foo 出现在结构、结构字段和全局命名空间中。
允许这种重复情况可能是因为需要额外的计算才能找到这些命名空间之间的冲突,而计算过去非常昂贵。
从那以后,C 保持向后兼容性,因为这就是 C 所做的。
编译器可以根据它们出现的上下文来区分它们。 C 2018 6.2.3,“标识符的命名空间”说:
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 any of the keywords
struct
,union
, orenum
);— 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).