C语言程序执行过程详解

计算机无法直接识别 C 语言程序,程序要想运行,必须先转换为机器指令。

通常,我们将编写好的 C语言程序称为源程序,存储源程序的文件称为源文件(后缀名为 .c)。将源程序转换为可执行的机器指令,需要经过「编译」和「链接」两个步骤。

编译

编译指的是将源程序转换为机器指令的过程。

对 C 语言程序的编译工作,由专门的软件完成,这样的软件称为编译器。

首先,编译器会执行一段特殊的程序,处理程序中以 # 号开头的代码,这段程序通常称为“预处理程序”或者“预处理器”。以#include <stdio.h>为例,预处理器会先找到 stdio.h 文件,然后将文件中的所有代码复制到 #include<stdio.h> 所在的位置,并取代后者。

经过预处理操作后,程序中绝大多数以 # 号开头的代码都会被处理掉,只有极个别的会留给编译器处理(例如 #pragma)。

接下来,编译器会检查程序中有没有错误,比如return 0后面少了;分号。如果发现错误,编译器会将“错误信息”反馈给程序员,有助于程序员快速修改程序。修改后的程序,要重新经历预处理和检查过程。

确认程序无误后,编译器将 C 语言程序“翻译”成机器指令,这些机器指令会保存到一个新建的、后缀名为 .o 或者 .obj 的文件中,通常称为目标文件。

编译器“翻译”程序的过程比较复杂,这里不再展开讲解,感兴趣的读者可以阅读《编译原理》这本书。

链接

经过编译后的 C 语言程序,虽然已经彻底转换为机器指令了,但指令还不完整,计算机无法执行。

实际开发中,我们通常会将一个完整的 C语言程序分散存储到多个源文件中,每个文件只存储一部分程序。编译器会逐一编译这些源文件,有多少个源文件,编译后就会产生多少个目标文件。每个目标文件中存储的都是一段机器指令,无法直接运行。

即便把 C语言程序写在一个源文件里,编译后只生成一个目标文件,文件中的机器指令仍不完整。因为 C语言程序中使用的 puts()、scanf() 等函数,它们的实现代码都保存在别的文件中,编译器无法找到并访问这些文件。

整合多个目标文件,以及查找某些函数的实现代码,这种工作全部都由链接器负责完成。

最终,链接器会生成一个后缀名为 .exe 的可执行文件,内部包含的就是完整、可运行的机器指令。

总结

C语言程序要想执行,必须经过编译和链接。

编译过程由编译器负责完成,会生成多个(≥1)后缀名为 .o 或者 .obj 的目标文件,文件中存储的是不完整的机器指令。

链接过程由链接器负责完成,最终会生成一个后缀名为 .exe 的可执行文件,文件中存储的是完整的机器指令。

© 版权声明
THE END
喜欢就支持一下吧
点赞1赞赏
分享
评论 抢沙发
HarryPotter的头像|艾奇编程网

昵称

取消
昵称表情