C语言程序设计案例式教程(第2版)
上QQ阅读APP看书,第一时间看更新

1.4 C语言程序的编译机制

早期的程序使用汇编语言编写,编写的汇编程序难移植,使得开发效率低下。C语言的出现使程序员在编程时可只关注程序逻辑本身,从而提高了编程的效率。那么计算机是如何理解C语言代码,进而运行程序、输出运行结果的呢?编译器会将编写的C语言程序翻译成计算机能够执行的指令和数据。计算机能够直接执行的指令和数据称为可执行代码。

C语言程序从源代码到可执行代码需要经过预处理、编译、汇编和链接4个步骤。例如,helloworld.c程序的编译过程如图1-17所示。

图1-17 helloworld.c程序的编译过程

下面以helloworld.c程序为例,并结合图1-17讲解C语言程序的编译过程。

(1)预处理

预处理主要处理代码中以“#”开头的预处理语句(预处理相关内容将在第10章讲解)。预处理完成后,会生成*.i文件。预处理操作具体包括以下几项。

● 展开所有宏(如#define),将宏替换为对应定义的值。

● 处理所有条件编译指令,例如#ifdef、#ifndef、#endif。

● 处理文件包含语句(如#include),将包含的文件直接插入语句所在的位置。

需要注意的是,代码中的编译器指令#pragma会被保留。除此之外,预处理还会进行以下操作。

● 删除所有注释。

● 添加行号和文件标识,以便在调试和编译出错时快速定位到错误所在行。

(2)编译

编译过程较复杂,需要进行词法分析、语法分析、语义分析、优化处理等工作,最终将预处理文件*.i转换成汇编文件*.s。编译的过程是优化的过程,包括中间代码优化和目标代码生成优化。

(3)汇编

汇编是指将生成的汇编文件*.s翻译成计算机能够执行的指令,生成的文件称为目标文件或者中间文件。Linux系统中的二进制文件是*.o文件,Windows系统中的二进制文件是*.obj文件,通常汇编生成的文件包含代码段和数据段。

(4)链接

生成二进制文件后,文件尚不能运行。若想运行文件,需要将二进制文件与代码中用到的库文件进行绑定,这个过程称为链接。链接是指处理程序中各个模块之间的关系,主要完成地址分配、空间分配、地址绑定等操作。链接操作完成后会生成可执行文件。

多学一招:静态库链接与动态库链接

链接分为静态库链接和动态库链接。

静态库文件在Linux系统中是*.a文件,在Windows系统中是*.lib文件。静态库文件本质上是一组目标文件的集合。静态库链接是指在程序链接过程中将包含某一函数功能的库文件全部链接到目标文件中。在程序编译完成后得到的可执行程序无须静态库支持。静态库链接能提高程序开发效率,但也会产生占用内存空间和模块更新难等问题。

动态库文件在Linux系统中是*.so文件,也称为共享库,在Windows系统中是*.dll文件。动态库链接是指在程序运行时只对需要的目标文件进行链接,因此程序在运行过程中离不开动态库文件。动态库链接可解决静态库资源浪费的问题,并且可实现代码共享、隐藏实现细节,便于升级维护。