- 论坛徽章:
- 19
|
本帖最后由 shenlanyouyu 于 2016-05-17 22:03 编辑
1:你所理解的编译过程包括哪些?每个过程的作用是什么?
以C/C++语言为例,程序编译的过程通常包含预处理、编译、汇编、链接。其中,编译过程包括词法分析、语法分析、语义分析和优化。
(1) 预处理的过程主要处理包括以下过程:
将所有的#define删除,并且展开所有的宏定义
处理所有的条件预编译指令,比如#if #ifdef #elif #else #endif等
处理#include 预编译指令,将被包含的文件插入到该预编译指令的位置。
删除所有注释 “//”和”/* */”.
添加行号和文件标识,以便编译时产生调试用的行号及编译错误警告行号。
保留所有的#pragma编译器指令,因为编译器需要使用它们。
(2) 编译过程
词法分析:识别出符号,从连续的字符中识别出标识符、关键字、数字、运算符并存储为符号(token)流。
语法分析:语法分析器将记号(Token)产生语法树
语义分析:经过语法分析生成的语法树,并不包含数据类型等语义信息,语义分析阶段会检查程序中是否含有语法正确但是存在逻辑问题的错误。
优化:源代码优化器,将整个语法书转化为中间代码(中间代码是与目标机器和运行环境无关的)。中间代码使得编译器被分为前端和后端。编译器前端负责产生机器无关的中间代码;编译器后端将中间代码转化为目标机器代码。
(3)汇编
汇编器是将汇编代码转变成机器可以执行的命令,每一个汇编语句几乎都对应一条机器指令。汇编相对于编译过程比较简单,根据汇编指令和机器指令的对照表一一翻译即可。汇编器依照选定操作系统的目标文件格式,将.s 文件转换为具体的目标文件。
(4)链接过程
最后链接器把一个或多个目标文件(库文件本质上也是目标文件)链接成符合选定操作系统指定格式的可执行文件。链接分为静态链接和动态链接。静态链接是指在编译阶段直接把静态库加入到可执行文件中去,这样可执行文件会比较大。而动态链接则是指链接阶段仅仅只加入一些描述信息,而程序执行时再从系统中把相应动态库加载到内存中去。
2:你平时用到的编译选项是什么?说明其作用
以GCC为例,常用的编译选项。
(1) -Wall 打开所有编译器告警选项,即编译器最严格告警模式。
(2) -O2 设置成为的优化级别为O2。
(3) -Idir... 把dir加到头文件的搜索路径中,而且gcc会在搜索标准头文件之前先搜索dir.
(4) -g 该选项主要为了调试程序。可以利用操作系统的“原生格式(native format)”生成调试信息。GDB 可以直接利用这个信息,其它调试器也可以使用这个调试信息。
(5) -shared –fPIC 编译生成.so共享库,–fPIC选项用于生成位置无关代码,以达到动态链接的目的。
(6) -pthread 编写多线程程序时使用。通过pthreads库加入对多线程的支持,这为预处理和连接设置了标志.pthread是POSIX指定的标准线程库。
3:如果让你自己做一个编译器,如何下手呢?
了解编译原理后,针对目标语言的特性,根据内存布局设计编译器。一个编译器是由一组有三个到四个组件(还有一些子组件)构成,数据以管道的方式从一个组件输入并流向下一个组件。对于词法分析、语法分析在GNU上面能够找到成熟的编译工具。以开发C程序编译器为例,可以使用Lex(Lexical Analyzar 词法分析生成器),Yacc(Yet Another Compiler Compiler编译器代码生成器)。 还可以使用flex/bison来根据语法生成编译器,只需要关注词法、语法的定义,得到语法树。
4:编译器和语言的关系是什么样的?
编译器当然是将对应语言的程序文本文件编译生成目标文件的工具,编译器也是一种可执行的程序,可以用其他语言编写。编译器由编译程序和运行库组成,编译程序负责将源程序翻译成为目标程序,运行库提供了一些基本的子程序给程序编写者使用。
|
|