标识符的名称空间如何在 C 中工作?

How do name spaces of identifiers work in C?

我知道名称空间在 C++ 中的工作方式,但我对它们在 C 中的工作方式有点困惑。因此,我对 C 中的名称空间进行了一些研究。

首先,ISO/IEC 9899:2018 (C18) 中的相应部分,第 6.2.3 节:

6.2.3 Name spaces of identifiers

1 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(32)) 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).


32) There is only one name space for tags even though three are possible.

所以这让我对 C 中的术语有了更多的理解,并且似乎通常与 C++ 中的目的相同。但不幸的是,标准中没有进一步说明名称空间在 C 中的工作方式。

显然,它与共享相同标识符的实体之间的区别有关,与 C++ 不同,我们在 C++ 中声明名称空间,例如:

namespace ctrl1 
{ 
    int max = 245; 
} 

并使用命名空间,例如:

using namespace ctrl1;

int a = ctrl1::max;

在 C 中,如果使用相应的标识符,编译器能够自动消除一个对象的特定用途的歧义。如果我错了,请纠正我。

这是如何运作的?编译器如何知道他是否应该在 C 中使用一个实体而不是另一个实体?


我看过Name spaces in c++ and c但是问题更侧重于C++,侧重于具体例子的处理。

我还阅读了 Name spaces in C,其中问题的目的再次更侧重于特定示例,这里是 enum 类型。


我的问题是:

in C, the compiler is be able to disambiguate a certain use of one object automatically if the respective identifier is used. Correct me, if I´m wrong.

How does that work? How does the compiler know if he shall use one entity instead of the other in C?

标准的摘录已经解决了这个问题(强调):

— label names (disambiguated by the syntax of the label declaration and use);

标签声明的形式是标识符后跟一个冒号,后面必须跟一个语句:

a_label:
do_something;

标签唯一使用goto语句中,goto语句中的标识符只能是标签:

goto a_label;

— the tags of structures, unions, and enumerations (disambiguated by following any32) of the keywords struct, union, or enum);

"Following any of the keywords struct, union, or enum" 正是它所说的意思:

struct a_tag
union another_tag
enum a_third_tag

这些形式可以出现在类型定义、类型声明和类型使用中。如果关键字 structunionenum 之一紧接在标识符之前,则该标识符是标签;否则不是。

— 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);

标识符作为 .-> 运算符的右侧操作数的出现将其区分为结构或联合成员的标识符。左侧操作数的类型决定 哪个 结构或联合类型。 C 结构和联合类型不能有静态成员,因此永远不需要访问相对于类型本身的结构或联合成员,缺少该类型的对象。

all other identifiers, called ordinary identifiers

其他三种情况之一未涵盖的任何内容都包含在这一情况中。这包括变量名称、函数名称、函数参数名称、内置和 typedefed 类型名称以及枚举常量。 (我认为这是一个完整的列表,但我可能忽略了一些东西)。

  • How do name spaces work in C?

我唯一能想到要澄清的另一件事是,与 C++ 不同,C 只有隐式声明和名称空间的使用。 C 中没有 namespace 关键字,也没有用于显式引用相对于所选名称空间的标识符的语法。用户定义的命名空间仅限于与结构和联合类型关联的命名空间,简单、隐式的方法令人满意地涵盖了所有可能的情况。

然而,鉴于普通标识符的类别非常广泛,可重用 C 库的作者通过在其库公开的外部标识符前加上特征性的短前缀来最小化名称冲突的可能性已成为一种惯例。这种 ad hoc 命名空间完全超出了标准的范围,但很常见。