程序员的自我修养第二章

编译和链接

2.1被隐藏的过程

#include<Stdio.h>
int main()
{
	printf("Hello World")
	return 0;
}

        我们用VS编译这段代码的时候只需右键项目文件,点击 生成 就可以生成exe文件。事实上,上述过程可分成四个步骤,分别是 预编译(Propressing), 编译(Compilation)汇编(Assembly)链接(Linking)请添加图片描述

2.1.1预编译

        首先是hello.c文件和stdio.h文件被预编译成一个.i文件。预编译过程主要处理那些已“#”开头的代码,比如“#define”、“#include”等。主要规则如下:

  1. 将所有的#define删除,并展开所有宏定义
  2. 处理所有的预编译指令,如#if、 #elif、 #endif等。
  3. 处理#include指令,将该包含文件插入到指令所在的位置,这个过程是递归的,也就是说包含的文件可能还会包含文件。
  4. 删除所有的注释(// ,/**/)
  5. 添加行号和文件标识
  6. 保留所有的#pragma指令

2.1.2编译

        编译是将预处理后的文件进行 词法分析语法分析语义分析优化后产生汇编代码文件的过程。

2.1.3汇编

        汇编器将汇编代码翻译成机器代码。每一条汇编指令几乎都对应一条机器指令。

2.1.4链接

        链接器将目标文件和库文件链接成EXE文件。

2.2编译器做了什么

        从最直观的角度看,编译器就是将高级语言翻译成机器语言的工具。比如我们可以使用C++写的程序,可以让编译器翻译成机器可以指定的指令和数据。
        编译过程一般分为六个步骤:扫描语法分析语义分析源代码优化代码生成目标代码优化

扫描器的任务很简单,只是进行简单的词法分析。
词法分析产生的几号一般分为几类:关键字标识符字面量(数字、字符串等)特殊符号(加号、减号等)

2.2.2语法分析

        语法分析器对扫描器产生的标记进行语法分析,并产生语法树,整个过程采用上线文无关的语法分析手段。语法分析器 产生的语法树是以表达式为节点的树,符号和数字是最小的表达式,通常作为语法树的叶子节点。在语法分析的同时很多运算符的优先级也被确定下来了。
        另外,有些运算法有特殊意义,比如C++里的 * 既可以标识乘号,又可以标识解引用,所以语法分析必须对两种情况进行区分。如果出现了表达式不合法,比如括号不匹配或缺少操作符等,编译器会报告语法分析时错误。

2.2.3语义分析

        语法分析仅仅是对表达式的语法层面的分析,但是它不知道这个语句是否有意义。比如两个指针做乘法运算是没意义的,但是它在语法分析时是合法的。
        编译器多能分析的语义是静态语义,即在编译器可以确定的语义,与之对应的是动态语义,即在运行期才能确定的语义。
        静态语义包括声明与类型匹配类型转换。比如把一个浮点数赋值给一个整数,隐含一个浮点数到整数的转换,语义分析要完成这个步骤。比如把一个浮点数赋值给一个指针,语义分析会发现类型不匹配,编译器会报错。动态语义一般指运行时出现的语义相关的问题,比如除0问题是一个运行期语义错误。
        经过语义分析阶段后,整个语法树的表达式都被标记了类型,如果某些类型涉及到隐式转换,语义分析程序会在语法树中插入相应的节点。

2.2.4中间语言生成

        现代编译器会有很多层次的优化,在原始代码级别会有一个优化过程。源代码级优化器将语法树转换成中间代码,它是语法树的顺序表示。其实它已经很接近目标代码了,只是它和机器和运营环境无关,比如它不包含数据的尺寸,变量地址和寄存器名字等。比较常见的中间代码有:三地址码 和P-代码。三地址码的基本形式是:

x = y op z

        中间代码是的编译器可以分成前端和后端。前端负责生成机器无关的中间代码,后端将中间代码转换成目标机器代码。这样对于一些可以跨平台的语言而言,可以针对多个平台使用一个前端,和针对不同平台的多个后端。

2.2.5目标代码生成与优化

        源代码级优化器产生中间代码,标志着其后的步骤都属于编译器后端。编译器后端主要包括代码生成器目标代码优化器代码生成器将中间代码翻译成机器代码,这个过程十分依赖目标机器,因为不同的机器有着不同的字长、寄存器、整数类型 和 浮点数类型。目标代码优化器对目标代码进行优化,如去掉多余的指令、用移位代替乘法和选择合适的寻址方式。

2.3 链接器

        编译好的目标代码里可能会引用其他模块的符号,链接器负责在各个模块之间查找被引用的符号。如果一个被引用的符号在所有模块里都没有找到 或者 多个模块定了相同的符号,链接器会报告错误。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值