【Linux】gcc

【Linux】gcc

在 Linux 系统下我们可以编写C语言程序并编译运行,我们就在本篇文章学习如何简单地编译运行C语言程序,并了解程序的翻译链接过程

使用gcc编译程序


首先我们要创建一个C语言文件,并编写代码

image-20240120220928518

使用 vim 编写代码,以如下代码为例

image-20240120221330098

使用gcc命令编译我们刚才写的代码,会产生一个可执行程序,这个可执行程序可以任意命名

gcc test.c

如果不命名,就会产生一个名为a.out的可执行文件

image-20240120221936669

我们也可以将这个可执行程序命名

gcc -o mytest test.c

image-20240120222054497

接着运行可执行程序,直接敲可执行程序的文件名,要说明文件所在目录,可以用绝对路径,也可以用相对路径

image-20240120222705272

image-20240120222830639

我们顺便也介绍一下c++程序的编译

编译C语言程序用的命令是gcc,而c++用的是 g++,因为c++兼容C语言,所以也可以用来编译C语言

c++文件以cppcxxcc结尾,这里我懒得打字,所以都用cc结尾

如有以下代码

image-20240120223717571

使用g++命令编译文件

g++ -o mytestcpp test.cc

如果使用 g++ 命令时出错,可能是没有安装,使用如下命令进行安装

sudo yum install -y gcc-c++

现在正常编译文件

image-20240120224218165

运行可执行程序

image-20240120224308825

程序的翻译过程


程序的翻译过程有:预处理、编译、汇编、链接

我们可以使用 gcc命令和选项查看过程

过程gcc命令命令的含义过程说明
预处理gcc -E test.c -o test.i从现在开始翻译 test.c文件,预处理完成就停下来,输出的文件为test.i预处理阶段,完成头文件展开、宏替换、去掉注释、条件编译
编译gcc -S test.i -o test.s从现在开始翻译test.i文件,编译完成就停下来,输出文件为test.s编译阶段,检查语法,将代码转为汇编代码
汇编gcc -c test.s -o test.o从现在开始翻译test.s文件,汇编完成就停下,输出文件为test.o汇编阶段,将汇编代码编译为二进制目标文件
链接gcc test.o -o mytest.exetest.o与库等进行链接,输出可执行文件mytest.exe形成可执行程序

下面我们来详细看一下上述过程究竟是怎样的

预处理


我们就从下面这个代码来看看头文件展开、去注释、 宏替换

image-20240126113657682

接着进行预处理

gcc -E test.c -o test.i

image-20240126113810552

预处理完成后,我们查看test.i文件

image-20240126114027788

可以看到,源文件只有十几行,预处理后产生的 test.i文件却有800多行。这就是头文件展开,实质就是将头文件的代码拷贝到我们的代码文件中

再来和源文件进行对比,宏M被替换为了 1 ,注释也被去掉了

image-20240126114427991

下面再来看条件编译,有以下代码

image-20240126115913206

进行预处理

image-20240126120017590

查看proj.i,可以看到,在没有定义V1V2时,默认使用是else下的代码

image-20240126120104261

我们可以在编译时定义宏,使用gcc -D就可以做到

image-20240126120558017

执行可执行程序

image-20240126120632165

也可以定义V2

image-20240126120729480

编译


test.i文件进行编译

gcc -S test.i -o test.s

image-20240126134017908

查看test.s文件,确实被转为了汇编

image-20240126134654512

汇编


test.s文件进行汇编,输出目标文件

gcc -c test.s -o test.o

image-20240126135146041

查看产生的目标文件
image-20240126135222019

链接


将目标文件与库进行链接,最终输出可执行程序

gcc test.o

image-20240126135341498

执行可执行程序

image-20240126135442124

链接


链接是什么?

——链接就是将我们写的程序和库结合的过程

好,那么库又是什么呢?

一个语言,在编写的时候必定会有许多标准和方法,比如我们常用的printf(),这时就会需要标准库来存放这些标准和方法,所以说一个语言一定要有自己的标准库。除了官方的标准库,还有许多第三方库可供我们使用。

在Linux下,我们可以使用如下命令查看一个可执行程序所链接的库

ldd 可执行程序名

image-20240126135818933

image-20240126140229222

有了标准库,我们也知道里面包含了许许多多的方法。那我们怎么知道有什么方法可以使用,又怎么使用呢?——这就需要头文件了,头文件就相当于库方法的说明书,我们可以根据头文件来调用库里的方法

动态链接与静态链接


库又分为动态库静态库

在Linux下,动态库后缀为.so,静态库后缀为.a,虽然Linux不需要用后缀区分文件,但我们使用者需要

在Windows下,动态库后缀为.dll,静态库后缀为.lib

既然库分为动态和静态,那么链接方式也就有动态链接静态链接
使用如下命令可以查看可执行程序的详细属性

file 文件名

image-20240126144813133

以上可执行程序使用的是动态链接,使用共享库

那么动态链接和静态链接又是怎么样的呢?下面我们就来看一下

动态链接

在编译阶段, 程序还没运行的时候,编译器就会将动态库的地址告知给程序。当程序运行时,程序要执行库方法时,就会顺着动态库的地址寻找动态库,在其中执行库方法,然后返回到程序中,继续向下执行

image-20240126152326744

动态链接的优缺点

  1. 依赖外部库。一旦动态库链接丢失或者动态库丢失,程序就运行不了了
  2. 节省资源。可执行程序中只有动态库的地址,用的时候直接跳转,不用开辟额外空间存储库;运行程序时,是在内存中运行,如果10个程序都用到了同一个方法,那么这个方法在内存中只要有一个即可,不用10个,即10个程序共用一个方法

静态链接

与动态链接不同的是,静态链接是在编译阶段将静态库本身本身拷贝到程序中,运行时直接在程序中调用,不需要用到库了

image-20240126153558069

静态链接的优缺点

  1. 一旦形成,和库无关,库怎样都不会影响程序运行
  2. 浪费资源。将库拷贝到可执行程序中,那程序本身就很大了;运行10个静态链接的程序时,即使10个程序中都用到了同一个方法,内存中也会存在10相同个方法

综上,一般编译器都是默认提供的动态库,gcc默认形成的可执行程序,都是动态链接的。下面就来验证一下

动静态链接的验证


gcc在编译.c文件时,默认是动态链接,我们可以使用如下指令来进行静态链接

gcc 源文件 -o 输出文件 -static

一般情况下,Linux是没有安装c/c++静态库的,可以使用如下指令安装

sudo yum install -y glibc-static libstdc++-static

现有test.c文件,我们可以对这个文件分别动态链接和静态链接

gcc test.c -o mytest-static -static
gcc test.c -o mytest

然后我们就可以发现,静态链接后的可执行程序大小比动态链接的大太多了

image-20240126160829039

我们也可以用ldd指令查看这两个可执行程序

image-20240126161027736

动态链接的程序有动态库,而静态链接的程序不能用ldd查看

接着用file来查看

image-20240126161220725

也可以看到一个是动态链接,一个是静态链接

结束,再见 😄

  • 17
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

阿洵Rain

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

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

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

打赏作者

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

抵扣说明:

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

余额充值