Linux编译器-gcc/g++使用

简介: ✅<1>主页:我的代码爱吃辣📃<2>知识讲解:Linux🔥<3>创作者:我的代码爱吃辣💬<4>前言:上期我们学习了vim写代码,今天了解gcc执行代码,和动静态库。

一.gcc介绍

gcc是一个C语言编译器,和我们平时用的VS2022不是一个概念,VS2022不仅可以编辑代码还可以编译执行代码。他是整合了很多功能的集成开发环境,简称IDE。gcc只负责编译C语言代码。

gcc 使用:

gcc [选项] 要编译的文件 [选项] [目标文件]




二.gcc翻译过程

(1)预处理(进行宏替换)

指令:

gcc -E test.c -o test.i



说明:

  • 预处理功能主要包括宏定义,文件包含,条件编译,去注释等
  • -E选项:让代码进行预处理,预处理之后就停下来。
  • -o选项:后面紧跟着的是生成的目标文件名称,上面的命令也可以写成:gcc -o test.i -E test.c

举例:

  1 #include<stdio.h>
  2 #define M 100
  3 #define MAX 10000
  4 int main()
  5 {
  6   printf("hello gcc%d\n",M);
  7   printf("hello gcc%d\n",M);
  8   printf("hello gcc%d\n",M);
  9   printf("hello gcc%d\n",MAX);
 10   printf("hello gcc%d\n",MAX);
 11   printf("hello gcc%d\n",MAX);                                                                                                                                                          
 12 
 13   return 0;
 14 }
 15 



我们发现,原本只有是几行的代码现在有了大还几百行。这就是因为在预处理阶段进行了头文件的展开,并且定义的宏也被替换了。

(2) 编译(生成汇编)

指令:

gcc -S test.i -o test.s



说明:

  • 在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc 把代码翻译成汇编语言。
  • “-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。

举例:

查看test.s文件:



(3)汇编(生成机器可识别代码)

指令:

gcc -c test.s -o test.o



说明:

  • 汇编阶段是把编译阶段生成的“.s”文件转成目标文件
  • 选项“-c”:代码翻译到汇编结束就停下来,就可看到汇编代码已转化为“.o”的二进制目标代码了


二进制文件test.o:



这既是二进制文件,我们当然是什么都看不懂了,这就是给计算机识别的文件。

那既然是二进制文件,可不可以执行呢?



告诉我们权限不够。

我们给他给予上执行权限:



告诉我们,test.o是无法执行的二进制文件,也就是说汇编生成的二进制文件是无法执行的。

(4)连接(生成可执行文件或库文件)

指令:

gcc test.o -o test



说明:

  • 命令没有选项。
  • 直接生成可执行的文件。

执行:



(5)总结gcc

我们在使用gcc 不必 预处理,编译,汇编 ,链接,一步一步的执行,我们可以直接使用

gcc C语言源文件 -o 目标文件

gcc选项


-E 只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面

-S 编译到汇编语言不进行汇编和链接

-c 编译到目标代码

-o 文件输出到 文件

-static 此选项对生成的文件采用静态链接

-g 生成调试信息。GNU 调试器可利用该信息。

-shared 此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库.

-O0

-O1

-O2

-O3 编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高

-w 不生成任何警告信息。

-Wall 生成所有警告信息


三.动静态链接库

(1)函数库

我们在上卖面写的代码里面使用了printf函数,但是我们并没有定义printf函数,而且stdio.h头文件里面也只有printf函数的声明而已。那是哪里实现的printf函数呢?

系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到

系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函

数“printf”了,而这也就是链接的作用。


也就是说没有库, gcc 就无法对代码进行翻译。


其实我们从人生中写的第一个代码输出"hello word",就一直在使用库,也就是语言库。


例如上面的写的C语言代码,翻译形成的可执行文件 test ,它也依赖了库。

我们可以使用命令 :ldd,来查看文件依赖那些库。

ldd 【文件】



我们甚至可以看一下命令依赖哪些库:



这里不能发现 ls 命令也是依赖库的, 甚至依赖着C语言库,因为我们的命令有相当一部分就是C语言写的,其实命令也就是程序。

(2) 动态库与静态库

函数库一般分为静态库和动态库两种:

  1. 1.静态库:格式为 lib***.a
  2. 2.动态库:格式为 lib***.so


d875448743eb4a07b3f62fc070ac3769.png


libc.so.6就是一个动态库,lib是前缀,so是后缀,c就是库名字,6是版本号,libc.so.就是C语言的库。


静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为“.a”

动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为“.so”,如前面所述的 libc.so.6 就是动态库。gcc 在编译时默认使用动态库。完成了链接之后,gcc 就可以生成可执行文件 ,gcc test.o -o test ,test就是生成的可执行文件。

gcc默认生成的二进制程序,是动态链接的,这点可以通过 file 命令验证。

(3)动态链接与静态链接

库的连接方式分为:动态链接和静态链接。


Linux下gcc默认是动态链接:

我们通过,file命令来查看可执行文件的连接方式。

file 【文件名】

我们将 file test 的内容输出重定向到 file.txt 中


33b8299f0355489dbd57cf774658580f.png


那为什么linux下gcc 不去使用静态链接呢?我们先了解一下动态链接和静态链接。


静态链接:连接的时候静态链接找到静态库,把库文件的代码全部加入到可执行文件中。

优点:静态链接成功,程序将不依赖任何库,自己就可以独立运行。

缺点:因为自身的拷贝的原因,比较房费空间。


动态链接:链接时动态链接找到动态库,拷贝动态库中代码的地址到可执行程序中的相关位置。

优点:因为可以做到被大家共享方法,所以真正的实现永远都是在库中,程序内部只有地址,比较节省空间。

缺点:我们的程序还是依赖动态库,一旦动态库失效,程序就无法运行。

而Linux下使用动态库的原因就是,一般对应的动态库并不会出问题,还可以减小空间的消耗,综合考虑动态库更优。


(4)静态链接的使用

我们使用gcc 就可以实现默认动态链接,如果我们就是想使用静态链接呢?静态链接需要特定的方式来实现,而且linux默认只安装了动态库,要想实现静态链接还得先安装静态库。

安装静态库:

sudo yum install -y glibc-static

安装以后使用命令:

gcc test.c -o test_static -static



我们将file test.static 内容输出重定向到 file.txt 中。



 test_static 就是静态链接生成的可执行文件,并且我们发现,静态链接生成的可执行程序的大小,远大于动态链接生成的可执行程序的大小。

相关文章
|
6天前
|
Linux C语言
suse linux 11 安装GCC开发环境
suse linux 11 安装GCC开发环境
11 0
|
6天前
|
编译器 Linux C语言
Linux:编译器 - gcc
Linux:编译器 - gcc
12 4
|
6天前
|
IDE Linux 开发工具
【Linux】 开始使用 gcc 吧!!!
我们在windows环境和macos环境里都有功能强大的集成开发环境(IDE)供我们使用 ,但是在Linux中我们如何编译运行我们的代码呢?这里就需要使用gcc / g++ 了。
27 0
【Linux】 开始使用 gcc 吧!!!
|
6天前
|
编译器 Linux C语言
【Linux】编译器-gcc/g++
【Linux】编译器-gcc/g++
28 2
|
6天前
|
Linux 编译器 C语言
Linux课程四课---Linux开发环境的使用(gcc/g++编译器的相关)
Linux课程四课---Linux开发环境的使用(gcc/g++编译器的相关)
|
1天前
|
运维 关系型数据库 MySQL
day03-Linux运维-Xshell优化和Linux系统命令入门(2)
day03-Linux运维-Xshell优化和Linux系统命令入门(2)
day03-Linux运维-Xshell优化和Linux系统命令入门(2)
|
1天前
|
运维 Linux Shell
day03-Linux运维-Xshell优化和Linux系统命令入门(1)
day03-Linux运维-Xshell优化和Linux系统命令入门(1)
day03-Linux运维-Xshell优化和Linux系统命令入门(1)
|
1天前
|
运维 程序员 Linux
运维最全Linux 基本防火墙设置和开放端口命令,2024年最新程序员如何自我学习和成长
运维最全Linux 基本防火墙设置和开放端口命令,2024年最新程序员如何自我学习和成长
|
1天前
|
运维 Ubuntu 安全
运维最全linux 命令行操作串口_linux串口命令(2),2024年最新Linux运维源码的Binder权限是如何控制
运维最全linux 命令行操作串口_linux串口命令(2),2024年最新Linux运维源码的Binder权限是如何控制
运维最全linux 命令行操作串口_linux串口命令(2),2024年最新Linux运维源码的Binder权限是如何控制
|
1天前
|
运维 Linux Perl
运维最全linux 命令行操作串口_linux串口命令(1),21年Linux运维面经分享
运维最全linux 命令行操作串口_linux串口命令(1),21年Linux运维面经分享
运维最全linux 命令行操作串口_linux串口命令(1),21年Linux运维面经分享

热门文章

最新文章