学科分类
目录
C语言

C程序编译过程

在前面小节提到早期的编程使用汇编进行编程,汇编程序难于移植,使得开发效率低下。C语言的出现使得编程关注程序逻辑本身,提高了编程的效率。那么计算机是如何理解C语言代码,进而执行程序,给出运行结果的呢?其中编译器的作用就是将编写的C源程序翻译成机器能够执行的指令和数据,机器能够直接执行的指令和数据称为可执行代码。C语言从源代码到可执行代码需要经过预处理、编译、汇编和链接四个步骤,如图1所示。

图1 编译原理

下面以“HelloWord.c”程序为例,并结合图1讲解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”文件。动态库链接指的是在程序运行时只对需要的目标文件进行链接,因此程序在运行过程中离不开动态库文件,动态库解决了静态库资源的浪费并且实现了代码共享、隐藏了实现细节、便于升级维护等特点。

image-20200519135644840多学一招:C语言编译器

C语言编译器在编译源码过程中会进行词法分析、语法分析、语义分析、中间语言生成、目标代码生成与优化、链接库文件(动态库或静态库)处理。不同的编译器对程序的优化处理不一样,本书中使用的MSVC编译器是微软公司专用于Visual Studio系列的编译器CL,其他常见的C语言编译器有GCC、MinGW、Clang、Cygwin。读者可查找相关资料使用编译器指令将源文件按照编译过程生成最终的可执行文件,对编译过程有更详细的了解。

点击此处
隐藏目录