链接属性决定如何处理在不同文件中出现的标识符。标识符的作用域也它的链接属性有关,但这两个属性并不相同。
没有链接属性的标识符(none)总是被当作单独的个体,也就是说该标识符的多个声明被当作独立不同的实体。
internal链接属性的标识符在同一个源文件内的所有声明中都指同一个实体,但位于不同源文件的多个声明则分属不同的实体。最后,属于external链接属性的标识符不管声明多少次、位于几个源文件都表示同一个实体。
图3.2的程序骨架通过展示名字声明的所有不同方式,描述了链接属性。在缺省情况下,标识符b、c和f的链接属性为external,其余标识符的链接属性则为none。因此,如果另一个源文件也包含了标识符b的类似声明并调用函数c,它们实际上访问的是这个源文件所定义的实体。f的链接属性之所以是external是因为它是个函数名。在这个源文件中调用函数f,它实际上将链接到其他源文件所定义的函数,甚至这个函数的定义可能出现在某个函数库。
图 3.2
关键字extern 和
static用于在声明中修改标识符的链接属性。如何某个声明在正常情况下具有external链接属性,在它前面加上static关键字可以合它的链接属性变为internal。例如,如果第2个声明
像下面这样书写:
static int b;
那么变量b就将为这个源文件所私有。在其他源文件中,如果也链接到一个叫做b的变量,那么它所引用的是另一个不同的变量。类似,也可以把函数声明为static,如下:
static int c(int d)
这可以防止它被其他源文件调用。
static只对缺省链接为external的声明才有改变链接属性的效果。例如,尽管你可以在声明5前面加上static关键字,介它的效果完全一样,因为e缺省链接属性并不是external。
extern关键字的规则则更为复杂。一般而言,它为一个标识符指定external链接属性,这样就可以访问在其他任何位置定义的这个实体。请考虑图3.3的例子。声明3为k指定external链接属性。这样一来,函数就可以访问在其他源文件声明的外部变量了。
从技术上说,这两个关键字只有在声明中才是必需的,如果3.3声明的3(它的缺省链接属性并不是external)。当用于具有文件作用域的声明时,这个关键字是可选的。然而,如果你在一个地方定义变量,并在使用这个变量的其他源文件的声明中添加external关键字,可以使读者更容易理解你的意图。
当extern关键字用于源文件中的一个标识符的第1次声明时,它指定该标识符具有external链接属性。但是,如果它用于该标识符的第2次声明时,它并不会更改由第1次声明所指定的链接属性。例如,图3.3中的声明4并不修改由声明1所指定的变量i的链接属性。
C和指针笔记 3.6链接属性,码迷,mamicode.com