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 就是静态链接生成的可执行文件,并且我们发现,静态链接生成的可执行程序的大小,远大于动态链接生成的可执行程序的大小。

相关实践学习
CentOS 7迁移Anolis OS 7
龙蜥操作系统Anolis OS的体验。Anolis OS 7生态上和依赖管理上保持跟CentOS 7.x兼容,一键式迁移脚本centos2anolis.py。本文为您介绍如何通过AOMS迁移工具实现CentOS 7.x到Anolis OS 7的迁移。
相关文章
|
1月前
|
Linux 编译器 C语言
【Linux快速入门(一)】Linux与ROS学习之编译基础(gcc编译)
【Linux快速入门(一)】Linux与ROS学习之编译基础(gcc编译)
|
3月前
|
Linux C语言
成功解决 在Linux CentOS 7 中安装gcc
这篇文章介绍了如何在Linux CentOS 7系统中安装gcc (g++) 8工具集。由于CentOS 7默认的gcc版本是4.8,而这个版本与Qt 5.14、Qt 5.15或更高版本不兼容,可能会导致编译时出现系统头文件错误。文章中提到,即使在项目配置中添加了`CONFIG+=c++11`,如果仍然报错,那么很可能是gcc版本的问题。为了解决这个问题,文章提供了使用CentOS的Software Collections (scl)来安装更新版本的gcc的步骤。
成功解决 在Linux CentOS 7 中安装gcc
|
2月前
|
Linux 编译器 C语言
Linux内核对GCC版本的检测
Linux内核对GCC版本的检测
|
3月前
|
Java Linux 编译器
【Linux】gcc简介+编译过程
【Linux】gcc简介+编译过程
|
5月前
|
Java 编译器 Linux
程序技术好文:详解Linux安装GCC方法
程序技术好文:详解Linux安装GCC方法
166 0
|
5月前
|
NoSQL 编译器 Linux
【Linux】--- Linux编译器-gcc/g++、调试器-gdb、项目自动化构建工具-make/Makefile 使用
【Linux】--- Linux编译器-gcc/g++、调试器-gdb、项目自动化构建工具-make/Makefile 使用
86 0
|
4天前
|
Linux
在 Linux 系统中,“cd”命令用于切换当前工作目录
在 Linux 系统中,“cd”命令用于切换当前工作目录。本文详细介绍了“cd”命令的基本用法和常见技巧,包括使用“.”、“..”、“~”、绝对路径和相对路径,以及快速切换到上一次工作目录等。此外,还探讨了高级技巧,如使用通配符、结合其他命令、在脚本中使用,以及实际应用案例,帮助读者提高工作效率。
22 3
|
4天前
|
监控 安全 Linux
在 Linux 系统中,网络管理是重要任务。本文介绍了常用的网络命令及其适用场景
在 Linux 系统中,网络管理是重要任务。本文介绍了常用的网络命令及其适用场景,包括 ping(测试连通性)、traceroute(跟踪路由路径)、netstat(显示网络连接信息)、nmap(网络扫描)、ifconfig 和 ip(网络接口配置)。掌握这些命令有助于高效诊断和解决网络问题,保障网络稳定运行。
17 2
|
12天前
|
缓存 监控 Linux

热门文章

最新文章