程序员的自我修养之:编译和链接

编程/开发
381
0
0
2022-08-03

我们学习每门语言,第一个小程序基本都是经典的“Hello Word”程序,每个程序员几乎闭着眼睛就能写出,编译运行一气呵成,但是我们很少关注编译和链接的过程,因为通常的开发环境都是流行的集成开发环境(IDE),IDE一般将编译和链接一步完成。这样就有很多系统软件的运行机制与机理被掩盖,导致程序程序很多莫名其妙的错误让我们束手无策。看到现象却看不到本质,下面我们就了解一下这些机制,先简单聊一聊编译与链接。

C语言的helloworld程序:

程序员的自我修养之:编译和链接

hello.c

在Linux下使用gcc编译只需要简单的一行命令,

程序员的自我修养之:编译和链接

gcc

实际上上述过程可以分解为4个步骤:预处理(Rrepressing)、编译(Compilation)、汇编(Assembly) 和 链接(Linking),如下图:

程序员的自我修养之:编译和链接

编译过程

1预处理

预处理是将源代码文件hello.c和相关头文件stdio.h被预编译器cpp预编译成一个.i文件。命令:

程序员的自我修养之:编译和链接

预编译

预编译过程主要助理那些源代码文件中的以“#”开始的预编译指令,如“#include”、“#define"、”#if“,并删除注释行,还会添加行号和文件名标识以便于编译时编译器产生调试用的行号信息及用于编译时产生编译错误或警告时能够显示行号。经过预编译的.i文件不包含任何宏定义,因为所有的宏已经被展开并且包含的文件也已经被插入到.i文件中。所以当我们无法判断宏定义是否正确或头文件包含是否正确时,可以查看已编译后的文件来确认问题。

2编译

编译过程就是把预处理玩的文件进行一系列的词法分析,语法分析,语义分析及优化后生成相应的汇编代码文件。

程序员的自我修养之:编译和链接

编译

注意:gcc命令只是一个后台程序的包装,会根据不同的参数要求去调用预编译编译程序cc1(c)、汇编器as、连接器ld。

3汇编

汇编器是将汇编代码转变成机器可以执行的命令,每一个汇编语句几乎都对应一条机器指令。汇编相对于编译过程比较简单,根据汇编指令和机器指令的对照表一一翻译即可。

gcc –c hello.c –o hello.o,由于hello.o的内容为机器码,不能以文本形式方便的呈现。

程序员的自我修养之:编译和链接

汇编

4链接

链接器ld将各个目标文件组装在一起,解决符号依赖,库依赖关系,并生成可执行文件。

ld –static crt1.o crti.o crtbeginT.o hello.o –start-group –lgcc –lgcc_eh –lc-end-group crtend.o crtn.o

编译和链接其实是一个很复杂的过程,后面我们详谈这部分。