编译,利用编译程序从源语言编写的源程序产生目标程序的过程。计算机只认识1和0,编译程序把高级语言语言换成二进制。
编译分为五个阶段:词法分析;语法分析;语义检查和中间代码生成;代码优化;目标代码生成。

Lex

Lex是美国Bell实验室M.Lesk等人用C语言开发的一种词法分析器自动生成工具,提供一种供开发者编写词法规则的语言以及这种语言的翻译器。基本工作原理为:由正规式生成NFA,将NFA变换成DFA,DFA经化简后,模拟生成词法分析器。

Lex源程序分为三部分,三部分之间以符号%%分隔。以%开头的符号和关键字,或者词法规则段的各个规则一般顶着行首来写,前面没有空格。

1
2
3
4
5
6
7
8
9
第一部分:定义段

%%

第二部分:词法规则段

%%

第三部分:辅助函数段

第一部分定义段写法

第二部分词法规则段写法

第三部分辅助函数段写法


GCC/G++

gcc [options] [filenames]

参数 描述
-c 只编译,不链接成为可执行文件
-o 指定输出文件名称
-g 产生符号调试工具所必要的符号信息
-O 对程序进行优化编译、链接
-O2 比 -O 更好的优化编译、链接
-Idirname dirname 所指出的目录加入到程序头文件目录列表中,是在预编译过程中使用的参数
-E 预编译后停下来,生成后缀为 .i 的预编译文件
-c 编译后停下来,生成后缀为 .o 的目标文件
-S 汇编后停下来,生成后缀为 .s 的汇编源文件
-pedantic gcc在编译不符合ANSI/ISO C 语言标准的源代码时,将产生相应的警告信息
-Wall 使 gcc 产生尽可能多的警告信息
-Werror 所有的警告当成错误进行处理
-Wcast-align 地址不需要对齐的指针指向一个地址需要对齐的变量地址时,则产生一个警告
-I 向 gcc 的头文件搜索路径中添加新的目录
-L 向 gcc 的库文件搜索路径中添加新的目录
-l 链接时装载函数库
-static 强制使用静态链接库
-shared 生成一个共享的目标文件
-g/-ggdb 不会将调试符号插入到生成的二进制代码中,因为这样会增加可执行文件的大小
-p/-pg 将剖析(Profiling)信息加入到最终生成的二进制代码中
-save-temps 保存编译过程中生成的一些列中间文件

测试 example.c

1
2
3
4
5
6
7
8
#include <stdio.h>

int main()
{
long long int var = 1;
printf("It is not standard C code!/n");
return 0;
}

编译原理之美

前端指的是编译器对程序代码的分析和理解过程。通常只跟语言的语法有关,跟目标机器无关。前端技术分为词法分析、语法分析和语义分析三个部分,主要涉及自动机和形式语言方面的基础的计算理论。

后端生成目标代码的过程,跟目标机器有关。

词法分析

词法分析器分析整个程序字符串,当遇到不同的字符时,会驱使它迁移到不同的状态。

语法分析

词法分析是识别一个个的单词,而语法分析就是在词法分析的基础上识别出程序的语法结构。

程序有定义良好的语法结构,语法分析过程就是构造这么一棵树。程序就是一棵抽象语法树(Abstract Syntax Tree,AST)。
树的每个节点(子树)是一个语法单元,这个单元的构成规则就叫语法。每个节点还可以有下级节点。

AST让计算机很容易去处理。


Reference:

  1. Yacc 与 Lex 快速入门(词法分析和语法分析)
  2. Lex使用指南
  3. gcc的使用简介与命令行参数说明
  4. 编译原理之美