第二章 编译和连接

简单的介绍了从源代码到可执行程序的编译。
更加详细的,需要去看《编译原理》了

编译和连接可以分解为四个部分:预处理,编译,汇编,链接。

从源代码到可执行程序

预处理

g++ -E test.c -o test.i
//不指定文件名,直接输出到控制台

预处理过程主要处理源代码中以#开头的预编译指令,比如#include,#define等等。
主要步骤为:

  1. 将所有的#define删除,并展开所有宏的定义
  2. 处理有多的田间预编译指令,#if,#ifdef,#else,#endif
  3. 处理#include预编译指令,将被包含的文件插入到该预编译指令的位置,这个过程是递归进行的。
    #include <>和“”的区别
  4. 删除所有注释
  5. 添加行号和文件名标识
    以便编译时,编译器产生调试用的行号信息,已经编译时产生的错误或者警告能够显示行号
  6. 保留所有的#pragma编译器指令,因为编译器需要使用他们

编译

g++ -S test.cc -o test.s
//cc1位编译程序

编译过程把预处理完的文件进行一系列的,词法分析,语法分析,语义分析以及优化后,产生县赢得汇编代码文件。
这个过程是整个程序构建的核心部分。

汇编

汇编过程是将编译产生的汇编代码转化为机器可执行的指令,每一条汇编语句对应一条机器指令。

g++ -c test.s -o test.o
//as是汇编器

链接

把各个模块之间的相互引用部分链接好,是的各个模块之间能够正确衔接。

编译器

编译过程(as编译器)分为6步:扫描、语法分析、语义分析、源代码优化、代码生成和目标代码优化。

扫描&词法分析

源代码被被输入到扫描器,然后进行词法分析,由代码中的字符差生一个个记号:关键字,标识符,字面量,特殊符号(+,-)

语法分析

语法分析对扫描器产生的几号进行语法分析,产生语法树。将词法分析产生的记号组合起来。
如果语法分析阶段,发现表达式不合法,比如少括号,少操作符,编译器便会报错。

语义分析

完成表达式中语法层面的分析,
静态语义:在编译器可以确定的语义,包括声明和类型的匹配,类型转换
动态语义:在运行期出现的予以相关问题,比如0作为被除数。

中间语言生成

将语法树转换为中间代码。同时进行了优化

代码生成和优化

代码生成器将中间代码转换成目标机器代码,这个过程依赖于机器,不同的机器有着不同的字长,寄存器等等。

你可能感兴趣的:(第二章 编译和连接)