Linux编译器
- 1.gcc/g++ 的使用
- 2. 程序的基本翻译过程
- 3.预处理
- 3.1验证预处理的功能(gcc -E)
- 4.编译(变成汇编语言)
- 4.1验证编译过程(gcc -S)
- 5.汇编(生成机器可识别代码)
- 5.1验证汇编过程(gcc -c)
- 6.链接(生成可以执行文件)
- 7.总结
1.gcc/g++ 的使用
gcc在Linux下负责编译C语言,g++主要负责编译C++,当然也兼容C语言。
我们先来以gcc为例子,看看怎么直接利用gcc编译我们代码
现在我们已经利用了vim编译器写好了代码,cat查看我们的代码,是要打印Hello World
接下来我们直接 输入 gcc myc.c 即可编译生成可执行程序,默认生成
a.out
接下来我们直接输入 ./a.out 运行即可
可以看到代码成功编译并执行了。
如果我们不想默认编译后生成a.out这个名称 我们可以在编译的时候可以这么输入: gcc -o myc myc.c
(myc可以改成你想要的名称)
可以看到myc也是可执行程序
以上是gcc使用方法
本篇文章主要讲的是一段程序执行的四个过程。
2. 程序的基本翻译过程
一段代码的执行可分为以下四个过程
1.预处理(进行宏替换等操作)
2.编译(生成汇编语言)
3.汇编(生成机器可识别码)
4.链接(生成可执行文件或库文件)
接下来我们逐一分析这四个过程的底层原理
3.预处理
预处理功能主要包括宏定义,文件包含,条件编译,去注释等。
预处理指令是以#号开头的代码行。
3.1验证预处理的功能(gcc -E)
因为代码如果直接gcc + C源文件的话,会直接把上面四个过程一下子执行完。 我们需要加上 -E 选项,只看预处理的功能,而不会一下子完四个过程。
-E:从现在开始进行程序的翻译,预处理做完,就停下来
接下来开始验证
我们先在myc.c里面加上宏定义,文件包含,条件编译,注释操作
然后输入
gcc -E -o myc.i myc.c
表示只执行到预处理并查看预处理后的文件,把该文件的内容放到 myc.i中
接下来,我们直接查看myc.i的内容
可以看到预处理后,本来只有几行的代码变成了800多行,因为我们的头文件在这里被展开了,宏定义和条件编译也被直接展开了,注释也不见了。
所以预处理这个阶段,会把代码变得更直接,更干净一些。
预处理阶段的代码还是我们的C语言代码。
4.编译(变成汇编语言)
4.1验证编译过程(gcc -S)
同样地,我们需要 -S 选项,验证编译过程
-S:从现在开始进行程序的翻译,编译做完就停下来
我们进行以下操作
gcc -S -o myc.s myc.i (这里用.i或者.c都行,因为.i是预处理阶段的文件)
当然也可以直接
gcc -S myc.i ,会默认生成myc.s文件
我们用vim查看myc.s文件
可以看到,我们的代码变成了汇编语言
5.汇编(生成机器可识别代码)
(汇编 -> 可重定位目标二进制文件,不可以被执行的 .obj文件) 这个阶段只把我们自己的代码进行翻译形成二进制目标文件
5.1验证汇编过程(gcc -c)
同样地,我们需要用 -c 选项验证汇编的过程
-c 从现在开始进行的程序的翻译,汇编做完就停下来。
我们输入gcc -c myc.s (当然也可以直接使用myc.c文件),这里的myc.s是上次已经编译好的。
这里会默认生成一个.o文件,也就是.obj文件
我们使用vim myc.s 打开这个文件
可以看到都是一堆乱码,这是一个二进制目标文件
6.链接(生成可以执行文件)
链接过程是把我们自己的.obj文件和库文件进行某种合并,形成可执行程序。编译器会自动寻找库文件完成链接,具体是如何完成的,可以看看我的其他文章。
gcc + obj文件
可以看到,确实生成了,a.out这个可执行文件
成功执行代码
我们的C程序中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实“printf”函数的呢?最后的答案是:系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函数“printf”了,而这也就是链接的作用
7.总结
所以即使是一段简单的打印Hello World程序,其底层原理也是非常复杂的,在这里只是简单地演示了程序执行的四个过程。
1.预处理
2.编译
3.汇编
4.链接
才能生成我们的可执行程序,而不是表面上简单地我们动动鼠标点击编译并运行就能完成的,那样只看到了事物的表面。我们要把一个东西学好就要知其然,也要知其所以然。
链接这个过程具体要用到动态库和静态库,可以看看
动态库和静态库这篇文章