C语言命名空间
目录

一、什么是命名空间?

命名空间(namespace) 表示标识符(identifier)的上下文(context)。 一个标识符可在多个命名空间中定义,它在不同命名空间中的含义是互不相干的。 这样,在一个新的命名空间中可定义任何标识符,它们不会与任何已有的标识符发生冲突,因为已有的定义都处于其它命名空间中。

在编程语言中,命名空间是一种特殊的作用域,且本身也用一个标识符来表示, 这样便将一系列在逻辑上相关的标识符用一个标识符组织了起来。 许多现代编程语言都支持命名空间。在一些编程语言(例如C++和Python)中, 命名空间本身的标识符也属于一个外层的命名空间,也即命名空间可以嵌套, 构成一个命名空间树,树根则是无名的全局名空间。

一些语言的命名空间:

  • C++: namespace关键字
  • Java: 包
  • Python: 模块

二、C语言的命名空间

C语言标准定义了4种命名空间:

1. label names

所有的label位于一个命名空间下;

2. the tags of structures, unions, and enumerations

全局的结构struct, 联合union 和 枚举enum,位于一个命名空间下;

3. the members of structures or unions

结构struct和联合union的成员位于它们各自struct或union命名空间下,相互独立互不影响,并且可以形成递归的命名空间(如struct中再定义struct)。

4. all other identifiers

所有其它的标识符,包括变量名、函数名、类型名(typedef)和枚举常量,位于一个命名空间下; 这里的标识符只的是全局标识符,必须通过其它文件可以访问到,局部标识符(static)不会污染这个命名空间。

因此可以看到,C语言预定义了3个全局的命名空间,并且可以通过再定义struct或union添加新的命名空间。

C语言的命名空间使得在一个大程序中,本来无关的模块,很容易使用同一名称表示不同的目的。 避免这种名称碰撞(name collision)的方法是标识符使用前缀,如模块名作为标识符的开始。

C语言的这种命名空间方式也造成了C和C++混合编程时的一些障碍,因为C++有复杂的命名空间规定,这导致在编译时对C和C++标示符的不同解析方式,这在以后再详细分析。

三、Tip

有一个tip是,由于结构struct和typedef类型名不在同一命名空间下, 因此诸如:

typedef struct Stack_T *Stack_T;

这样的定义一个Stack_T类型时可以的,并不会产生标识符冲突。

还有一个是以下方式并没有冲突:

struct A { int a };
int A;

但这在C++中却会产生冲突,这也是C++的命名空间和C不同的结果。

发表评论