Linux编译器-gcc或g++的使用

作者 : admin 本文共2274个字,预计阅读时间需要6分钟 发布时间: 2024-06-10 共2人阅读

一.安装gcc/g++

linux中是不会自带gcc/g++的,我们需要编译程序就自己需要安装gcc/g++。

很简单我们使用简单的命令安装gcc:sudo yum install -y gcc

g++安装:sudo yum install -y gcc-c++

我们知道Windows上区分文件,都是使用文件后缀来区分的,.txt是文本文件,.mp4是视频文件,.md是markdown文件等等。

在linux中一切皆文件,一个文件可以随便取名字,但是这样好吗?不见得。比如下面这样。

Linux编译器-gcc或g++的使用插图

test.txt文件中我编写的是c代码,使用gcc编译器编译该文件,显然从结果来看,是编译不过的。

使用mv修改test.txt为test.c,再使用gcc编译就能编译过了。

Linux编译器-gcc或g++的使用插图(1)

结论:虽然linux中不关心文件的后缀,但是gcc/g++是要区分文件后缀的,gcc编译.c后缀的c文件,g++编译.cc/.cpp后缀的c++文件。

二.一个文件到可执行程序的步骤

在我们编一个源文件的时候,使用gcc或者g++时,都会直接生成可执行程序。
那为什么要生成可执行程序呢?因为机器只认识二进制语言,它可不懂什么代码,汇编,我们的目的就是把源代码变成机器语言,也就是二进制语言。

其实生成可执行程序之前都会有好几个步骤的:

先经过预处理,再编译,在汇编,在进行链接生成可执行程序,接下来我们就一步一步探讨一下具体步骤的作用。

1.预处理

预处理的主要功能:

①头文件的展开
②去注释
③条件编译
④宏替换

预处理的命令:gcc -E test.c -o test.i

这里的-E就是预处理的意思,-o是生成test.i文件。

编写代码来验证一下。

 #include
  2 #define M 10
  3 
  4 #define v1 1
  5 int main()
  6 {
  7     //这是条件编译                                                          
  8 #if v1
  9     printf("这是普通版本的
");
 10 #elif v2
 11     printf("这是会员版本的
");
 12 #else
 13     printf("这是超级会员版本的
");
 14 #endif
 15   printf("%d",M);
 18     return 0;
 19 }

Linux编译器-gcc或g++的使用插图(2)

可以看出上面几百行全是stdio头文件的展开,然后我们写的注销也全部没有了,定义的宏M也被替换成了10,条件编译也成功的实现了,通过条件编译,可以实现对代码的动态裁剪

2.编译

编译就是把预处理后的文件生成汇编的过程。

编译的命令:gcc -S test.i -o test.s

验证:

Linux编译器-gcc或g++的使用插图(3)

可以看出这里就是各种汇编的指令,我们也看不懂。

3.汇编

汇编也就是把汇编语言变成二进制语言。

汇编的命令:gcc -c test.s -o test.o

Linux编译器-gcc或g++的使用插图(4)

这就是可被机器识别的目标文件(obj文件)。

4.链接

链接就是生成可执行程序。

链接命令:gcc test.o

链接可不是这么简单就完了,它还牵扯到库文件,待会细说。

三.gcc选项记忆

上面我们说到预处理,编译等,使用的命令是不是不好记,这里有个好记忆的方法。

使用的命令-E -S -c刚好对于键盘上的键ESC,只不过要记清楚,ES是大写,c是小写的。

依次生成的文件是iso,而在Windows中,iso是光盘镜像文件。

这样联系起来也就比较好记了。

但是我们实际上我们得到可执行文件,可不用这么复杂,直接使用gcc该文件即可。

四.函数库之静态库和动态库

对于printf函数这些,为什么我们代码中写了,电脑就知道它实现的是什么功能呢?

因为我们包含了头文件?也不全对,因为stdio头文件只是各种声明,还有各种宏定义而已。

我们现在所写的代码都是站在巨人的肩膀上,已经有人帮我们写好了可以直接可以使用的函数,也就是函数的实现,那这些函数在哪里呢?我怎么没有看到。

这就要引出来我们要说的库了,库包含各种函数的实现。

可执行程序=我们写的代码+头文件+库。

使用命令ls /lib64/libc.so.6可以查看库的位置。

Linux编译器-gcc或g++的使用插图(5)

而库也分为静态库和动态库。默认情况下,云服务器上是没有安装c静态库的,只有动态库。

一般来说,linux中.so为动态库,Windows中.dll为动态库。

linux中.a为静态库,Windows中.lib为静态库。

安装c++静态库的命令:sudo yum install -y libstdc+±static。
安装c静态库的命令:sudo yum install -y glibc-static。

动态库是c/c++或者其他第三方提供的所有方法的集合,被所有程序以链接的方式关联起来。(动态链接)

这里的动态链接是库中所有的函数,都有入口地址,所谓的动态链接,其实就是把要连接的库中的函数地址拷贝到我们的可执行程序的特定位置!

静态库是c/c++或者其他第三方提供的所有方法的集合,被所有程序以拷贝的方式,将需要的代码,拷贝到自己的可执行程序中。(静态链接)

我们可以将test.文件分别使用静态链接和动态链接得到可执行程序,来看看有什么区别。

动态链接:

Linux编译器-gcc或g++的使用插图(6)

静态链接:

Linux编译器-gcc或g++的使用插图(7)

test-d是动态链接出来的可执行文件,而test-s是静态链接出来的可执行文件,可以很清晰的看出,静态链接出来的可执行程序的文件大小是远大于动态链接的。

这里就可以总结出它们的优缺点了。

动态链接的优点:形成的可执行程序体积较小,比较节省资源的!
缺点:强依赖动态库,动态库没了,所有的依赖这个库程序都无法运行了。

静态库的优点:无视库,可以独立运行。
缺点:体积太大,浪费资源。

就像刚开始我们下载vs开发环境的时候,下载安装包内存不大,当我们选择c/c++下载得到时候,大小就会达到几个G。
这是因为当我们下载的开发环境的时候,它默认会为我们做以下工作:

①下载头文件,lib。
②设置合理的查找路径。

本站无任何商业行为
个人在线分享 » Linux编译器-gcc或g++的使用
E-->