编译与连接

2019-10-18  本文已影响0人  王技术

在 Xcode 中按下 command + B
不出意外的话, 就会显示小锤子
小锤子下面是 Build Succeeded
Build 就是构建
其实构建是一个很复杂的过程
大致的分为 预处理 编译 汇编 链接 四个步骤
最近看了 程序员的自我修养 这本书和一些相关的博客
整理一下构建过程的细节


预编译

在构建的第一步是预编译
预编译做的事比较简单, 大概是:


编译

编译过程就是将预处理完的文件进行一系列操作 : 词法分析 语法分析 语义分析 优化并生成汇编代码
这个过程是构建程序最核心的部分, 也是最复杂的部分.

记号 类型
array 标识符
[ 左方括号
index 标识符
] 右方括号
= 赋值
( 左圆括号
index 标识符
+ 加号
4 数字
) 右圆括号
* 乘号
( 左圆括号
2 数字
+ 加号
6 数字
) 右圆括号

词法分析产生的记号一般分为以下几类 : 关键字 标识符 字面量(数字 字符串) 特殊符号(加号 等号),
与此同时, 扫描器还完成了其他工作 : 将标识符存放到符号表, 将数字字符串常量存放到文字表等.

现在的编译器有着很多层的优化, 往往在源码级就会有一个优化过程, 由源码级优化器完成, 比如 (2+6) 这个表达式, 在编译器就可以被确定, 生成如下语法树 :


优化后的语法树

其实直接在语法树上做优化比较困难, 所以源码优化器往往把整个语法树转换成中间代码, 他是语法树的顺序表示, 已经非常接近目标代码, 但是他一般跟目标机器和运行时环境是无关的, 比如他不包含数据的尺寸, 变量地址和寄存器的名字等. 中间代码使编译器被分为前端和后端, 编译器前端负责生产与机器无关的中间代码, 编译器后端将中间代码转换成目标代码. 这样对于一些可以跨平台的编译器而言, 他们可以针对不同的平台使用一个前端数个后端.


链接

经过 扫描 语法分析 语义分析 源代码优化 目标代码生成 目标代码优化 这一系列操作, 源码被编译成了目标代码, 但是目标代码有一个问题, index 和 array 的地址还没有确定, 如果 index 和 array 和源代码在同一个编译单元, 那么编译器可以为他们分配空间, 如果定义在别的程序模块就没办法了.

现在程序的代码规模往往很大, 所以每个程序会被分为多个模块, 这样做的好处是每个模块之间相互依赖又相互独立, 而且模块可以单独开发编译测试, 便于重用. 但是随之而来的问题就是模块之间怎么通信, 模块之间的通信包括函数的调用和变量的访问, 函数的访问需要知道函数的地址, 变量的访问需要知道变量的地址.

上一篇 下一篇

猜你喜欢

热点阅读