从extern说开去(一)


extern符号的主要目的是为了实现C++对C程序的正确调用,在C++中完美兼容C。

包含的含义主要有两个方面:

(1)extern关键字表明函数和全局变量的作用范围。从链接的角度看,意味着在编译期间会以约定的方式表示引用的在其他模块中声明的函数或变量,等到链接时再重定位,进行地址修正(绝对地址修正和相对地址修正)。与之相对应的是static,用static声明后的函数和变量无法被其他模块引用。

(2)遇到由extern声明的部分,C++编译器会以C的方式进行编译。

逐条来看具体含义。

首先要搞清楚,我们通常所说的编译并不准确。从源代码到可执行文件,要经历4个主要步骤预编译 -> 编译 -> 汇编 -> 链接。

与extern相关的主要在链接和编译的过程,所以主要讲解这两个过程。

首先看看链接(因为相对简单)。

链接的本质是把多个不同的目标文件互相粘合在一起。编译器编译源代码后生成的文件叫做目标文件,从广义上看目标文件与可执行文件的结构是一致的,区别在于由于没有经过链接的过程,引用的不是在本模块内定义的函数和全局变量只能以约定的方式表示,并不能获得实际的内容。以hello world程序举例

#include<stdio.h>

int main()
{
    printf("hello world!\n");
    return 0;
}
上述代码中,调用了printf函数。函数名就是一个指针,指向代表函数代码片段的入口地址。而函数的代码片段在哪呢?或者说函数名这个指针指向哪里呢?答案就是函数定义的模块。也就是说,对于一个完整的可执行文件,printf指向这个函数代码片段的位置,也就是指向定义这个函数的模块的某一个位置。而在链接之前,编译的过程中这个值会以约定的方式代替,链接的作用就是将具体的地址填入。

搞清了链接的作用,我们就可以知道,对于一个目标文件,它所用的符号(函数和变量统称为符号),如果是在它内部定义的(也就是在源代码中定义),它可以直接获取到这个符号的地址,即时不链接也可以直接用。而对于在其他文件内定义的符号(它所引用的,比如printf),只有在链接之后才能获得具体地址。

既然有可以被其他模块引用的符号(链接之后获得地址的符号),那么自然也就有不可以被其他模块所引用的符号(static声明)。

这就是extern的第一个含义。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章