C&C++编译过程

--参考:(C语言的编译链接过程详解)http://7905648.blog.51cto.com/7895648/1297255+(C&C++的编译过程详解)http://blog.csdn.net/microzone/article/details/6707327

------------------------------------------------------------------------

--C/C++编译过程主要分为4个过程:1) 编译预处理 2) 编译、优化阶段 3) 汇编过程 4) 链接程序

结果:源代码----编译器---->汇编代码----汇编器---->目标代码---链接器---->可执行程序

============编译预处理============

     预处理阶段,在正式的编译阶段之前进行。预处理阶段将根据已放置的文件中的预处理指令来修改源文件的内容。如#include指令就是一个预处理指令,他把文件的内容添加到.cpp文件中。这个在编译之前修改源文件的方式提供了很大的灵活性,以适应不同的计算机和操作系统环境的限制。一个环境所需要的可执行代码跟另一个环境所需要的可执行代码可能有所不同,因为可用的硬件体系结构和操作系统不同所致。在许多情况下(特别是在嵌入式开发中),可以把用于不同环境的代码放在同一个文件中,再在预处理阶段修改代码,使之适应环境。主要包括:

--宏定义指令,如#define Name TokenString,#undef等。 
--条件编译指令,如#ifdef,#ifndef,#else,#elif,#endif等。预编译程序将根据有关的文件,将那些不必要的代码过滤掉;
--头文件包含指令,如#include "FileName"或者#include <FileName>等。
--特殊符号,预编译程序可以识别一些特殊的符号。在源程序中出现的LINE标识符将被解释为当前行号(十进制),FILE则被解释为当前被编译的C源程序的文件名称,FUNCTION则被解释为当前被编译的C源程序中的函数名称。预编译程序对于在源程序中出现的这些串将用合适的值进行替换,这些常常是配套使用,用来进行对程序的调试,

--预处理模块 预处理工作由#pragma命令完成,#Pragma命令将设定编译器的状态或者是指示编译器完成一些特定的动作。

--说明:预处理阶段并不属于预编译过程。预编译程序所完成的基本上是对源程序的"替换"工作。经过此替换后,生成一个没有宏定义、没有条件编译指令、没有特殊符号的输出文件。这个文件的含义同没有经过预处理的源文件是相同的,但内容有所不同

============ 编译、优化阶段============
      经过预编译得到的输出文件中,只有常量;如数字、字符串、变量的定义,以及C语言的关键字,如main,if,else,for,while,{,}, +,-,*,\等等。 编译程序所要做的工作就是通过词法分析和语法分析,在确认所有指令都是符合语法规则之后,将其翻译成等价的 中间代码表示或汇编代码
在《编译原理》中我们可以了解到一个编译器对程序代码的编译主要分为下面几个过程:
a) 词法分析
b) 语法分析
c) 语义分析
d) 中间代码生成
e) 代码优化
f) 代码生成
g) 符号表管理
h) 将多个步骤组合成趟

i) 编译器构造工具 

        优化处理是编译系统中一项比较复杂高深的技术。它涉及到的问题不仅同编译技术有关,而且跟机器的硬件环境也有关。优化一部分是对中间代码的优化,这种优化不依赖于具体的计算机。另一种优化则主要针对目标代码的生成而进行的,这种优化与硬件环境有莫大的关系。
         对于前一种优化,主要的工作是删除公共表达式、循环优化(代码外提、强度消弱、变换循环控制条件、已知量的合并等)、复写传播及无用赋值的删去等等。
        后一种类型的优化同机器的硬件结构密切相关,最主要的是考虑是如何充分利用机器的各个硬件寄存器存放的有关变量的值,以减少对于内存的访问次数(要知道内存资源对于计算机至关重要,控制好它可以大幅提高计算机的运算速度)。另外,如何根据机器硬件执行指令的特点(如流水线、RISC、CISC、VLIW等)而对指令进行一些调整使目标代码比较短,执行的效率比较高,也是一个重要的研究课题。

============ 汇编过程============

       汇编过程实际上指把汇编语言代码翻译成目标机器指令的过程。对于被翻译系统处理的每一个C语言源程序,都将最终经过这一处理而得到相应的目标文件。目标文件中所存放的也就是与源程序等效的目标的机器语言代码。 目标文件由段组成。通常一个目标文件中至少有两个段:

--代码段:该段中所包含的主要是程序的指令。该段一般是可读和可执行的,但一般却不可写。 

--数据段:主要存放程序中要用到的各种全局变量或静态的数据。一般数据段都是可读,可写,可执行的。 

============ 链接程序============

         由汇编程序生成的目标文件并不能立即就被执行,其中可能还有许多没有解决的问题。例如,某个源文件中的函数可能引用了另一个源文件中定义的某个符号(如变量或者函数调用等); 在程序中可能调用了某个库文件中的函数,等等。所有的这些问题,都需要经链接程序的处理方能得以解决。

         链接程序的主要工作就是将有关的目标文件彼此相连接,也即将在一个文件中引用的符号同该符号在另外一个文件中的定义连接起来,使得所有的这些目标文件成为一个能够诶操作系统装入执行的统一整体。 根据开发人员指定的同库函数的链接方式的不同,链接处理可分为两种:

--静态链接:在这种链接方式下,函数的代码将从其所在地静态链接库中被拷贝到最终的可执行程序中。这样该程序在被执行时这些代码将被装入到该进程的虚拟地址空间中。静态链接库实际上是一个目标文件的集合, 其中的每个文件含有库中的一个或者一组相关函数的代码。
--动态链接 :在此种方式下,函数的代码被放到称作是动态链接库或共享对象的某个目标文件中。 链接程序此时所作的只是在最终的可执行程序中记录下共享对象的名字以及其它少量的登记信息。在此可执行文件被执行时,动态链接库的全部内容将被映射到运行时相应进程的虚地址空间。动态链接程序将根据可执行程序中记录的信息找到相应的函数代码。
        对于可执行文件中的函数调用,可分别采用动态链接或静态链接的方法。使用动态链接能够使最终的可执行文件比较短小,并且当共享对象被多个进程使用时能节约一
些内存,因为在内存中只需要保存一份此共享对象的代码。但并不是使用动态链接就一定比使用静态链接要优越。在某些情况下动态链接可能带来一些性能上损害,例如移植性将大大降低。

你可能感兴趣的:(C&C++编译过程)