两个具有相同名称的外部对象实际上代表的是同一个对象,即使编程者本意并非如此,但系统却会如此处理。因此,如果在两个不同的源文件包括了定义
int a;
那么,它或者表示程序错误(如果连接器禁止外部变量重复定义的话),或者在两个源文件中共享a的同一个实例(无论两个源文件的外部变量a是否应该共享)。
即使其中a的一个定义是出现在系统提供的库文件中,也仍然进行同样的处理。当然,一个设计良好的函数库不至于定义a作外部名称。但是要了解函数库中定义的所有外部对象名称却也并非易事。类似于read和write这样的名称不难猜到,但其他的名称就没有这么容易了。
ANSI C定义了C标准函数库,列出了经常用到因而可能会引发命名冲突的所有函数。这样,我们就容易避免与库文件中的外部对象名称发生冲突。如果一个库函数需要调用另一个未在ANSI C标准列出的库函数,那么它应该以“隐藏名称”来调用后者。这就使得程序员可以定义一个函数,比如函数名为read,而不用担心库函数getc本应调用库文件中的read函数,却调用了这个用户定义read函数。但大多数C语言实现并不是这样做,因此这类命名冲突仍然是一个问题。
static修饰符是一个能够减少此类命名冲突的有用工具。例如,以下声明语句
static int a;
其含义与下面的语句相同
int a;
只不过,a的作用域限制在一个源文件内,对于其他源文件,a是不可见的。因此,如果若干个函数需要共享一组外部对象,可以将这些函数放到一个源文件中,把它们需要用到的对象也都在同一个源文件中static修饰符声明。
static修饰符不仅适用于变量,也适用于函数。如果函数f需要调用另一个函数g,而且只有函数f需要调用函数g,我们可以把函数f与函数g都放到同一个源文件中,并且声明函数g为static:
static int g(int x) { /* g函数体 */ } void f() { /* 其他内容 */ b = g(a); }
我们可以在多个源文件中定义同名的函数g,只要所有函数g都被定义为static,或者仅仅只有其中一个函数g不是static。因此,为了避免可能出现的命名冲突,如果一个函数仅仅被同一个源文件中的其他函数调用,我们就应该声明该函数为static。
未经允许不得转载:TacuLee » C陷阱与缺陷之命名冲突与static修饰符