欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C/C++从源码到可执行程序的过程讲解

程序员文章站 2022-07-05 22:38:54
C/C++源码生成平台下的可执行文件,需要经过3个步骤:预处理、编译、链接。 1. 预处理 将宏、条件编译指令、头文件包含等指令进行展开。也就是说,这是一个代码替换的工作。...

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无法自动进行。

这就是为什么需要人为复制库文件到生成的可执行目录下。而且程序的清理等操作也不会影响到可执行目录下的这些库文件。