Posts 程序编译链接过程
Post
Cancel

程序编译链接过程

C++的编译链接过程

在linux环境下开发C++时,理解编译、链接的原理和过程对于linux C++程序来说是一项基本功。将代码转变为可执行程序的过程大致可分为如下阶段:预编译,编译和链接。

预编译

预编译过程主要处理那些源代码文件中的以“#”开始的预编译指令。比如“#include”、”#define”等,主要的处理规则如下: 1.将所有的#define删除,并展开所有的宏定义 2.处理所有的预编译指令,比如#if,#ifdef等 3.处理#include预处理指令,将被包含的文件插入到该预编译介绍信的位置。该过程是递归的,所有包含的文件都将插入。 4.删除所有的注释//与/**/区域 5.添加行号和文件名标识。例如__LINE__ 6.保留所有的#pragma编译器指令,因为编译器需要使用。   提示,GCC中可使用-E来指示编译器只进行预编译。这时候所有的宏已经展开,并展开所有的包含文件,当我们无法判断宏定义或头文件包含是否正确时,可以查看预编译后的文件来确定问题。

编译

  接下来就是编译:把预处理文件进行一系列记法分析、语法分析、语义分析及优化后生成相应的汇编文件。现在的编译器可分为编译器前端和编译器后端。前端是与机器无关的处理,生成中间代码,后端是与处理有关的优化等。linux中最常用的编译器是GCC,注意GCC是一系列后台编译程序的包装,它会根据不同的参数去调用预编译程序cc1、汇编器as、链接器ld。

  从最直观的角度的角度讲,编译器就是将高级语言翻译成机器语言的工具。比如我们用C/C++语言写的一个程序可以使用编译器将其翻译成机器可以执行的指令及数据。编译过程一般可以分为6个步骤:扫描、语法分析、语义分析、源代码、代码生成和目标代码优化。

1
 SourceCode---scanner--->>Tokens---parser--->>SyntaxTree---SemanticAnalyzer--->>CommandSyntaxTree--->SourceCodeOptimizer------>>In

  以一段简单的C语言代码为例讲述整个编译过程:     array[index]=(index+4)*(2+6)

  词法分析:源代码被输入到扫描器(Scanner),扫描器的任务很简单,它运用一种类似于有限状态机(Finite State Machine)的算法将源代码字符序列分割成一系列的记号(Token)。记号一般分为五类:关键字、标识符、常量、运算符、界符。有一个叫lex的程序可以实现词法扫描,它会按照用户之前描述的词法规则将输入的字符串分割为一个个记号。

  语法分析:将对由扫描器产生的记号进行语法分析,从面产生语法树(Context Tree)。由语法分析分析器生成的语法树就是以表达式(Expression)为节点的树。语法分析也有一个现成的工具叫做yacc。也像lex一样,可以根据用户给定的语法规则对输入的记号序列进行解析,从而构建出一棵语法树。

语义分析

  语义分析。编译所能分析的语义是静态语义,所谓静态语义是指在编译期可以确定的语义,与之对应的动态语义就是只有在运行期才能确定的语义。静态语义通常包括声明和类型的匹配,类型的转换。比如当一个浮点型的表达式赋值一个整型表达时,其它隐含了一个数据类型的转换,由语义分析来完成。动态语义一般指在运行期出现的语义相关的问题,比如将0作为除数是一个运行期语义错误。在linux中运行期的语义错误表现为内核对执行进程的一个信号(signal)。如SIGSEGV,若不进行预定处理,这些错误常常导致程序coredump。一个高可靠的程序应该捕获这些信号,给出明确的错误的提示。

编译器后端

中间代码生成

  中间代码代码生成。这里主要进行源代码级的优化,在上例中(2+6)这个表达式就可以被优化掉,因为它的值在编译期就可以被确定。中间代码使得编译器可以被分为前端和后端。编译器负责产生机器无关的中间代码,编译器后端将中间代码转换成目标机器代码。这样对于一些跨平台的编译器而言,它们可以针对不同的平台使用同一个前端和针对不同机器平台的数个后端。

目标代码生成与优化

  目标代码生成与优化:代码生成器和目标代码优化器。代码生成器将目标代码转换成目标机器代码,这个过程依赖目标机器,因为不同的机器有着不同的字长、寄存器等。最后目标代码优化器对上述的目标代码进行优化,比如选择合适的寻址方式、使用位移来代替乘法运算、删除多余的指令等。

总结

  现在的编译器有着异常复杂的结构,这是因为现代高级编译语言本身非常地复杂,比如C++语言的定义就极为复杂,至今没有一个编译器能够支持C++语言标准所规定的所有语言特性,并且C++还在不断的进化中,C++11已经在推广使用,C++14标准已经发布,C++17也将在不久的将来面试。做为IT狗也要努力跟上步伐,不断学习背后姿势,才能不断进步。

This post is licensed under CC BY 4.0 by the author.