简单的介绍了从源代码到可执行程序的编译。
更加详细的,需要去看《编译原理》了
编译和连接可以分解为四个部分:预处理,编译,汇编,链接。
从源代码到可执行程序
预处理
g++ -E test.c -o test.i
//不指定文件名,直接输出到控制台
预处理过程主要处理源代码中以#
开头的预编译指令,比如#include
,#define
等等。
主要步骤为:
- 将所有的
#define
删除,并展开所有宏的定义 - 处理有多的田间预编译指令,
#if
,#ifdef
,#else
,#endif
- 处理
#include
预编译指令,将被包含的文件插入到该预编译指令的位置,这个过程是递归进行的。
#include <>和“”的区别 - 删除所有注释
- 添加行号和文件名标识
以便编译时,编译器产生调试用的行号信息,已经编译时产生的错误或者警告能够显示行号 - 保留所有的
#pragma
编译器指令,因为编译器需要使用他们
编译
g++ -S test.cc -o test.s
//cc1位编译程序
编译过程把预处理完的文件进行一系列的,词法分析,语法分析,语义分析以及优化后,产生县赢得汇编代码文件。
这个过程是整个程序构建的核心部分。
汇编
汇编过程是将编译产生的汇编代码转化为机器可执行的指令,每一条汇编语句对应一条机器指令。
g++ -c test.s -o test.o
//as是汇编器
链接
把各个模块之间的相互引用部分链接好,是的各个模块之间能够正确衔接。
编译器
编译过程(as编译器)分为6步:扫描、语法分析、语义分析、源代码优化、代码生成和目标代码优化。
扫描&词法分析
源代码被被输入到扫描器,然后进行词法分析,由代码中的字符差生一个个记号:关键字,标识符,字面量,特殊符号(+,-)
语法分析
语法分析对扫描器产生的几号进行语法分析,产生语法树。将词法分析产生的记号组合起来。
如果语法分析阶段,发现表达式不合法,比如少括号,少操作符,编译器便会报错。
语义分析
完成表达式中语法层面的分析,
静态语义:在编译器可以确定的语义,包括声明和类型的匹配,类型转换
动态语义:在运行期出现的予以相关问题,比如0作为被除数。
中间语言生成
将语法树转换为中间代码。同时进行了优化
代码生成和优化
代码生成器将中间代码转换成目标机器代码,这个过程依赖于机器,不同的机器有着不同的字长,寄存器等等。
网友评论