程序员的自我修养之编译和链接

一个程序的源代码到变成可执行程序,要经过 --预处理—编译—汇编–链接四个过程。
1. 预处理都做了啥?
指令: gcc -E hello.c -o hello.i
预处理主要处理源代码中以“#”开头的预编译指令,主要包括:

  • 将所有的“#define”删除并展开所有的宏定义。 处理所有条件预编译指令,比如“#if”"#ifdef""#else"“endif”

  • 处理#include预编译指令,将被包含的文件插入到该编译指令的位置。 删除所有的注释 “//” “/**/”

  • 添加行号和文件名标识,比如#2 “hello.c” 2, 以便编译时编译器产生调试用的行号信息*,及用于编译时,*产生编译错误或警告时能够显示行号

  • 保留所有的#pragma编译器指令,因为编译器需要使用它们

2. 编译都做了啥?
指令:gcc -S hello.i -o hello.s
把预处理完的文件进行一系列词法分析,语法分析,语义分析,及优化后产生相应的汇编代码(目标代码)文件。
2.1 词法分析—将源代码的字符序列扫描分割成一系列的记号。例如:
code: arry[index] = (index + 4) * (2 + 6)
上面语句会被拆分为:

记号类型
arry标识符
[左方括号
index标识符
]右方括号

…略
2.2 语法分析
将扫描器产生的记号进行语法分析,从而产生语法树(syntax tree),语法树是以表达式(expression)为节点的树。例如:arry[index] = (index + 4) * (2 + 6)
这是一个包含赋值表达式,加法表达式,乘法表达式,数组表达式,括号表达式组成的复杂表达式。
符号和数字是最小的表达式,所以他们是末端子节点。
语法分析过程中会确定运算符号的优先级。
如果发现表达式不合法,比如括号不配对,表达式中缺少操作符,变编译器将报错。
在这里插入图片描述
2.3 语义分析
分析整条语句是否有意义,包括:
静态语义:编译期间可以确定的语义。通常包括声明和类型的匹配,类型转换
动态语义:运行期间可以确定的语义。如,0 作为除数。
语义分析后,语法树的表达式都被标示了类型
在这里插入图片描述
2.4 代码优化
将语法树转换成中间代码(常见的有三地址码—(例如 x = y op z)和P-代码)
中间代码使得编译器被分为前端和后端。前端负责产生机器无关的中间代码。后端负责将中间代码转换成目标机器代码(跨平台编译发生在后端)

3. 汇编都做了啥?
指令: gcc -c hello.s -o hello.o
汇编是将汇编代码转变成机器可以执行的指令,汇编过程没有复杂的语法,只是根据汇编指令和机器指令的对照表一一翻译过来。输出的是目标文件(object file)。

4. 链接都做了啥?
链接过程主要包括 地址和空间分配,符号决议和重定位。
连接器的主要功能是重定位,每个需要修正的地方叫做一个重定位入口(relocation entry),重定位就是给程序中每个这样的地址引用的位置“打补丁”,使它们指向正确的地址。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值