【Linux】Linux编译器-gcc/g++的使用和程序执行的基础底层原理

文章详细介绍了Linux下使用gcc/g++编译C/C++程序的过程,包括预处理(宏替换、文件包含等)、编译(生成汇编语言)、汇编(生成机器码)和链接(生成可执行文件)四个步骤,并通过实例验证了每个阶段的功能。预处理使用-E选项,编译使用-S选项,汇编使用-c选项,最终链接生成a.out或自定义命名的可执行程序。文章强调理解这些底层原理对于学习编程的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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.链接
才能生成我们的可执行程序,而不是表面上简单地我们动动鼠标点击编译并运行就能完成的,那样只看到了事物的表面。我们要把一个东西学好就要知其然,也要知其所以然。
链接这个过程具体要用到动态库和静态库,可以看看
动态库和静态库
这篇文章

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fun gun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值