链接属性
当组成一个程序的各个源文件分别被编译之后,所有的目标文件以及那些从一个或多个函数库中引用的函数链接在一起,形成可执行程序。
如果相同的标识符出现在几个不同的源文件中时,它们表示相同的实体,还是表示不同的实体?标识符的链接属性(linkage)决定如何处理
在不同文件中出现的标识符。标识符的作用域与它的链接属性有关。
external(外部)、internal(内部)和none(无)。没有链接属性的标识符(none)总是被当做单独的个体,也就是说该标识符的多个声明被当做
独立不同的实体。internal链接属性的标识符在同一个源文件内的所有声明中都指同一个实体,但位于不同源文件的多个声明则分属不同
的实体。external链接属性的标识符不论声明多少次,位于几个源文件中都表示一个实体。
typedef char *a; //1
int b; //2
int c_func(int d) //3 4
{
int e; //5
int f_func(int g); //6 7
...
}
标识符b、c和f链接属性为external,其余标识符的链接属性为none。因此,如果另一个源文件中也包含了标识符b的类似声明并调用函数c
实际上访问的是这个源文件中所定义的实体。f的链接属性之所以是external是因为它是一个函数名。在这个源文件中调用函数f,它实际上
将链接到其他源文件所定义的函数,甚至这个函数的定义可能出现在某个函数库。
关键字extern和static用于在声明中修改标识符的链接属性。如果某个声明在正常情况下具有external链接属性,在它前面加上
static关键字可以使它的链接属性变为internal。如果第2个声明像下面这样书写:
static int b;
那么变量b就将为这个源文件所私有。
类似,也可把函数声明为static
static int c_func(int d)
这样可以防止它被其他文件调用。
static只对缺省链接属性为external的声明才有改变链接属性的效果。
extern关键字规则更为复杂。一般而言,它为一个标识符指定external链接属性,这样就可以访问在其他任何位置定义的这个实体。
这样就可以访问在其他源文件声明的外部变量了。
从技术上说,这个两个关键字只有在声明中才是必须的,声明3(它的缺省链接属性并不是external),当用于具有文件作用域的声明时,这个关键字是可选的。
然而,如果你在一个地方定义变量,并在使用这个变量的其他源文件的声明中添加external关键字,可以使读者更容易理解你的意图。
当extern关键字用于源文件中一个标识符的第一次声明时,它指定该标识符具有external链接属性。但是,如果它用于该标识符的第2次或以后的声明
时,它并不会修改由第一次声明所指定的链接属性。声明4并不会修改声明1所指定的i的链接属性。
static int i; //1
int func()
{
int j; //2
extern int k; //3
extern int i; //4
}
阅读(1680) | 评论(0) | 转发(0) |