引言:
时间过的飞快,可以看出我们已经开始学习Linux了,但是我们学习Linux过程中,依然会涉及到很多的以前的知识,比如编译原理,我们的代码如何从一个源文件逐步变成一个可执行文件,当初我记得我在哔哩哔哩上看鹏哥的免费的C语言的课的时候,C语言的最后一节课讲的就是编译原理的内容,但是随着时间的流逝,我们应该可以发现,我们对这方面的知识是比较的薄弱的,我感觉我都快忘记有这个东西了,更不要说具体的过程和原理了。所以今天让我们借着Linux操作系统,我们来复习一下我们的编译原理并且进一步的掌握。当时鹏哥讲的时候用的就会Linux操作系统给我们上的课,只是因为当时我们并没有学习Linux,所以我们对鹏哥的一些讲解的过程可以说是非常的盲目的,很多东西都是学的一知半解,但是今天的我们是有Linux操作系统的我们,所以接下来我们就使用我们的Linux来进一步的学习编译原理这块内容。
创建文件
首先我们在学习C语言的时候,我们都知道,我们在使用VS写代码的时候,我们都需要创建一个工程,创建一个源文件,并且身为比特人我们一般都会把这个源文件的名称设置为万年不朽的:test.c这个文件可以说是计算机专业的学生在学习过程中的一个必建文件了,但是我们关注的并不是文件的名称,我们比较关注的是它的后缀(.c),所以下述我们的讲解过程,我们就把我们的源文件称为test.c
编写代码
身为计算机专业的我们,编写代码可以说是我们最重要的事情,没有之一,所以当我们创建好了文件之后,我们要进行的就是代码的编写,写出正确的,高效的,安全的代码就是我们的目标。当然这个是一个需要日积月累的过程,无论是笔试中的做题,还是学习过程中的练习。我们一定要相信自己,孰能生巧是真的。
编译代码
每当我们写完了我们的代码,我们通常是会进行一个编译的过程,从而判断我们自己的代码是否是正确的,合理的,符合标准的,我们通常就是进行(Ctrl+F5)的操作,但是当我们按下了这两个按钮之后,会发现我们需要等待几秒之后,才会在我们的显示屏上看到我们程序的运行结果。
显然我们等待的那几秒,我们的编译器帮助我们完成了编译的过程,但是在我们前期写代码的时候,我们只需要会进行Ctrl+F5的操作就行了,我们这个叫做知其然。
但是古话说的好,知其然还要知其所以然,所以我们顺理成章的可以展开接下来的话题:
编译的具体原理
【我们的所以然】
编译原理包括:预处理、编译、汇编、链接
源文件(后缀.c) |
---|
预处理(后缀.i) |
编译(后缀.s) |
汇编(后缀.o) |
链接 |
我们现在就逐一开始具体理解,当然此时我们是在Linux的环境下
预处理
指令:gcc -E test.c -o test.i ------ 表示:将我的test.c文件进行预处理完之后,再把预处理之后的代码存到test.i中
这样我们就得到了预处理之后的test.i文件了(我们就可以进到文件之中看一下我们自己的代码和预处理之后的代码的区别了)
打开后如图:test.i
看到上述图片,我们对照着图片进行对比式讲解
相信大家从小就知道找不同游戏,我们今天就也来玩一玩找不同游戏,回归童年
不同点1:我的源文件只有29行代码,而我的tesst.i文件却有865行代码 |
---|
不同点2:在我的main函数上方多了一串代码 |
不同点3:在我的main函数中我的相关代码的内容发生了改变,我的注释代码被清除了 |
不同点4:我的 #define N 20 被替换到了相应的数组中 |
不同点5:我们的判断条件printf (“hello newday”)被执行了 |
所以我们此时可以去打开我们的stdio.h头文件中看一看
指令:vim stdio.h
发现:我的stdio.h就是我的test.i文件中的前面的内容
我大致的截取一些,如果全部接下来是非常的占用位置,所以……
所以根据以上证据,我可以证明,我们的预处理生成test.i文件
包括了头文件的展开合并到源文件这个步骤 |
---|
并且根据第二个不同点,得到预处理包括去注释的功能 |
根据第四个不同点,得到预处理包括宏替换的功能 |
根据第五个不同点,得到条件会被直接编译的功能 |
总结:预处理包括头文件的展开合并到源文件,条件编译,宏替换,去注释等
编译
指令:gcc -S test.i -o test.s => 表示:将我预处理之后的test.i文件进行C语言转换成汇编语言,然后把转换成汇编语言之后的文件存到test.s文件中, 这样我们就得到了C语言转换为汇编语言之后的test.s文件了(我们就可以进到文件之中看一下C语言变成汇编语言之后是什么样子的了)
打开文件图片:test.s
上述就是我么的test.s文件中的内容,也就是test.i文件变成了test.s文件
也就是把我们的C语言转换成了一个我们更加看不懂的语言(汇编语言)
汇编
指令:gcc -c test.s -o test.o => 表示:将我的汇编语言文件转换成一个二进制的文件,然后把这个二进制的文件存到test.o文件中
这样我们就得到了汇编语言变成二进制test.o文件了(我们就可以进到文件之中看一下此时的test.o文件是长什么样了)
打开后的图片:test.o
此时这个就是我们的二进制文件,更看不懂
但是注意:此时的这个test.o 文件是一个不可执行文件(因为:还没有进行链接)
所以我们可以发现,编译过程是为了让你更加的看不懂,从而让电脑更加的看的懂的过程
链接
具体链接过程如图:
链接过程无明显现象,我们不做过多解释
但是如下图:
我们可以知道在链接过程其实是调用了我们的C语言库的 libc-2.17.so