前言
这是我们学习代码的最重要的一个知识点之一,因为我们要去运行一个代码并不是简单的去直接出结果,而是经过了很多我们看不到的步骤,我们在这里以C语言为例子在Linux的环境下讲解,大家没有学过Linux的不用担心,最后会有一个思维导图,直接看就行。
一、总体步骤
1. 翻译环境:在这个环境中,源代码会被翻译成机器可以读懂的二进制指令
2. 执行环境:实际执行代码
二、翻译环境
翻译环境从整体角度就是执行了下面的事情:
1. 源文件经过编译器生成对应的目标文件
2. 链接库和目标文件通过链接器生成对应的可执行程序
3. 链接器同时也会引入标准C函数库中任何被该程序所用到的函数,而且它可以搜索程序员个人的程序库,将其需要的函数也链接到程序中。
二、具体化的翻译环境
三、解读翻译环境
3.1 预处理阶段
如图所示,预处理主要是处理我们的头文件,注释和预处理指令;
我们可以使用下面的指令来观察现象:
gcc -E test.c > test.i
预处理完成之后就停下来,预处理之后产生的结果都放在test.i文件中。
下面就是操作之后的图:
预处理阶段的test.i | |
头文件 | 被展开,展开后又700多行 |
注释 | 被删除 |
预处理指令 | 被替换 |
关于预处理指令可以看我的这篇博客:http://t.csdnimg.cn/Cl0OI
3.2 编译阶段
在编译阶段中我们也有相应的指令:
gcc -S test.c
编译完成之后就停下来,结果保存在test.s中。下面就是操作之后的图:
在这一步就是把C代码翻译成汇编指令,可以检查我们的语法,词法和语义。通常的编译错误就是我们的语法,词法或者语义出现了错误;
符号汇总就是将我们的全局变量,函数等汇总到一起。
3.3 汇编阶段
在汇编阶段的指令是:
gcc -c test.c
汇编完成之后就停下来,结果保存在test.o中。下面是操作之后的图:
因为在test.o文件里放的都是二进制指令,我们是没办法看懂的,但是里面有一个ELF我们是可以看懂的。
因为在test.o里是按照ELF格式存储的,所以我们输入如下指令可以翻译ELF文件:
readily -a test.o
翻译之后,在汇编这里是 形成了符号表,符号表就是将符号汇总的放在一个表里,如下:
3.4 链接阶段
这个就是在多文件的时候,可以将多文件的符号表给合并到一起,因为我们每个.c文件都会经过编译,所以在最后链接到时候,链接就像一捆绳子,将很多个.c文件整合在一起。
合并段表:将多文件合并
合并符号表:合并多文件里的函数的定义和声明,各个符号表放在一起。
在这里的错误通常是链接失败,原因就是你在多文件中,某个函数没有定义,符号表里没有这个函数
四、执行
执行没啥说的,编译链接通过了,执行就没啥讲的了;
给大家一个指令来执行c语言的文件吧
//编译
gcc test.c
//编译通过生成a.out文件,再执行
./a,out