C/C++从源码到可执行程序的过程讲解
C/C++源码生成平台下的可执行文件,需要经过3个步骤:预处理、编译、链接。
1. 预处理
将宏、条件编译指令、头文件包含等指令进行展开。也就是说,这是一个代码替换的工作。
C/C++源码经预处理后,不再存在各种宏指令。但展开后依然是代码的形式,是人可读的。
2. 编译
将C/C++代码翻译成汇编代码,然后翻译成平台的机器代码。最终会生成一个与cpp文件同名的目标文件,其后缀名为.o或者.obj。目标文件以二进制形式存在。
通常一个目标文件有两个段:
① 代码段
② 数据段
这一步工作量最大,也是最耗费时间的一步。
3. 链接
将3中生成的目标文件与各种所需的库文件进行链接,生成平台可执行文件。
链接器除了将目标文件与库文件进行链接,还负责未解决符号的链接。未解决符号指extern等关键字修饰的符号。
链接分为两种:
① 内部链接:若一个名称(变量或者函数)对于它的编译单元(cpp)来说是局部的,且在链接时不与其他编译单元相同的名称冲突,那么该名称有内部链接。
② 外部链接:若一个名称(变量或者函数)在链接时可以与其他编译单元(cpp)交互,那么该名称具有外部链接。
由上可知,由于.h文件会被多个编译单元(即.cpp)包含,若.h中有定义,那么每个包含这个.h文件的编译单元都会对同一个符号进行定义,若该符号为外部链接,那么该定义为所有编译单元可见,从而会导致duplicatedexternal symbols链接错误(注意这是个链接错误)。故若头文件中要进行定义,那么必须保证定义的符号只有内部链接。
C++特点:
对于C++而言,一个编译单元指一个.cpp文件和它所include的所有.h文件。 预处理时,.h中的代码会替换#include指令,从而扩充到.cpp中。
然后编译器编译该.cpp文件,生成一个.obj文件,这就是二进制的目标文件。
当编译器将所有.cpp都编译完成后,链接器将目标文件与库文件进行链接,生成一个.exe文件或者库文件。
VisualStudio的工作:
VisualStudio是一个开发工具集,对于C/C++程序而言,它集成了编译器和链接器。
1. VisualStudio读取配置,确定标准函数库与头文件。包括环境变量中的路径。
2. VisualStudio确定源代码之间的依赖关系。
所谓依赖关系,是指B文件引用了A文件,那么就必须先编译A,再编译B。故根据依赖关系,编译器必须满足:
① 只有A编译完成后,B的编译才可以开始
② 当A变化后,B会被重新编译
实际上,编译顺序被保存在configure脚本所生成的makefile文件中。这就是为什么编译时要先运行configure。
可知,确定编译顺序的同时,编译所用到的头文件也确定了。
3. VisualStudio进行预编译头文件的编译
4. VisualStudio进行预处理,替换掉各种宏命令
5. VisualStudio进行编译,将源码转换为汇编代码,然后转换为目标代码(机器码)
6. VisualStudio进行链接。若为静态链接,将函数库复制到可执行文件目录下;若为动态链接,则只在运行时动态调用。
注意静态链接复制函数库这样的操作需要人为进行,VisualStudio无法自动进行。
这就是为什么需要人为复制库文件到生成的可执行目录下。而且程序的清理等操作也不会影响到可执行目录下的这些库文件。
上一篇: DB2编程序小小技巧
下一篇: python实现KNN近邻算法