「Linux工具」gcc/g++

引言:欢迎大家再次来到小鸥的Linux栏目内容,今天我们继续介绍Linux学习中可能会遇到的工具,博主学习这部分时使用的时centos 7系统,所以也是在此基础上做学习分享。
本篇重点介绍gcc/g++及其相关的编译链接过程、动静态连接、动静态库的部分扩展内容

本篇专栏:Linux专栏

作者主页:海盗猫鸥-CSDN

gcc/g++及其相关概念

编译器gcc/g++

gccg++操作选项都相同,gcc用于编译c语言,g++用于编译cpp

实际上gcc和g++的使用是非常简单的,所以我们重点就在相关概念的补充和理解上

程序编译过程

当不观察编译过程时,直接使用gcc/g++ .c文件 -o 可执行文件生成可执行文件即可(使用)

与其相关的更多的命令行选项,我们在今后的学习中过程中逐步遇到逐步了解即可,不用死记硬背。

预处理(宏替换)

  1. 预处理阶段主要进行宏替换,文件包含,处理条件编译,去注释等操作
  2. gcc -E code.c -o code.i:开始翻译,在预处理阶段完成后停下来,处理内容放到code.i文件中
  3. 选项-E,作用是让gcc在预处理结束后停止编译过程。
  4. 选项-o,后更上要形成的目标文件,文件code.c经预处理后生成code.i

生成.i文件

vim查看文件:

编译(生成汇编)

  1. 编译阶段,gcc会检查代码规范性,是否有语法错误等问题,检查无误后,gcc将预处理完成后的代码翻译成汇编语言
  2. gcc -S code.i -o code.s开始翻译,编译阶段完成后停止,生成到文件code.s中(code.i可以换为code.c,此时就相当于code.c开始重新处理文件,会再经过预处理一次)
  3. 选项-S:让文件编译完成后后停止,生成汇编代码

生成.s文件

vim查看文件:此时为汇编语言

汇编(生成机器码)

  1. 汇编阶段,会将编译阶段生成的.s文件转成目标文件
  2. gcc -c code.s -o code.ogcc开始编译,完成汇编阶段后停止,结果放入目标文件code.o(二进制文件)
  3. 选项-cgcc在完成汇编阶段后停下来,此时.o文件已经是二进制文件

生成.o文件

vim查看文件:已经是二进制文件,所以我们看到的都是乱码

链接(生成可执行文件)

  1. 汇编完成后,最后一步就是链接阶段,会将所有需要的.o文件链接起来形成一个可执行文件
  2. gcc code.o -o code

动态链接和静态链接

我们都知道的是,对于一个完整可行的项目,一定是由许多不同的文件共同构成的,不可将所有代码都放到一个源文件中。这也就意味着各个不同的源文件之间一定存在着各种各样的依赖关系(比如一个文件要用到另一个文件中定义的函数)。

但我们经过上面的编译过程知道,++每个源文件都是独立编译的,每个.c源文件都会生成一个.o的目标文件++,而为了满足各个文件之间的依赖关系,就需要将这些不同的文件之间进行链接,最后生成生成一个可执行程序,也就是上述编译过程的最后一步。

而文件链接分为两种方式:

静态链接

静态链接过程中,链接器会分析源文件目标文件(如code.o)中的符号引用,从静态库中有选择地提取 被引用的代码和数据段,然后将这些提取的部分与源文件的.o文件合并 成一个全新的可执行程序。

静态链接生成的可执行程序完全不依赖外部共享库 ,因为在链接过程中所有需要的库代码都已经被静态地链接到可执行程序 中(简单说,就是代码编译后会有一份使用到的静态库内容的拷贝),使得程序可以独立运行

然而,静态链接也存在明显缺点:

  1. 文件体积较大:每个可执行文件都包含完整的库代码副本
  2. 存储空间浪费:多个程序使用时,磁盘上会存在多份相同的库代码
  3. 内存使用效率低:运行时每个进程都有独立的库代码副本,无法共享内存中的库代码
  4. 更新困难:库代码更新时需要重新编译链接所有依赖的程序

动态链接

动态链接过程中,链接器会先记录下源文件目标文件code.o中对动态库引用的相关信息,然后生成一个包含了这些重定位信息的可执行文件中。

这样我们在运行动态链接的程序时,内存中就会先加载这个可执行文件,然后根据其中记录的动态库依赖信息,将所需的动态库也加载到内存,并完成地址重定位(将符号引用解析为实际内存地址),这样在程序需要时就可以根据地址来调用动态库中的函数

动态链接的程序无法脱离动态库执行独立执行,动态库出问题将导致依赖于它的所有程序也出问题,且不同版本之间也可能存在兼容性问题

但相++较于静态链接++ ,动态链接有许多优点

  1. 文件体积小:不会包含动态库中的代码
  2. 内存使用效率高:多个可执行程序可以共享一个加载到内存中的动态库,也因此称为共享库
  3. 便于更新:动态库文件更新时,只要接口调用方式不变,就不需要改变源码

动态库和静态库

动态链接时使用的库就是动态库,静态链接时使用的库就是静态库。

动态库后缀:.so(Linux).dll(Windows)

静态库后缀:.a(Linux) .lib(Windows)

而系统中的库文件都放在/lib64/目录下

ldd查询链接库信息

可以查看可执行程序所链接的库信息

其中的其中的libc.so.6就是该文件用到的一个库,去掉前面的lib和后缀名后,就是这个库的名字,所以图中的库其实就是C标准库

file查看链接方式

file指令可以查看可执行文件的链接方式

而Linux中的默认链接方式就是动态链接,我们也可以手动静态链接来看看效果:

使用指令gcc code.c -o code-static -static,其实就是正常的编译指令加上选项-static即可

由于默认没有安装C静态库,所以使用静态链接失败,我们需要手动安装一下C静态库

安装C静态库sudo yum install glibc-static -y(sudo需要指定用户被加入到相关配置文件中后,对应用户才可以使用)

此时我们再生成静态链接的code-static

此时使用fileldd命令查看其相关库和链接信息:

sudo问题

我们学会使用vim后就可以来修改配置文件了

要想普通用户能使用sudo提权,需要修改配置文件,使用vim打开/etc/sudoers文件

将需要sudo的用户名加入到root后面,该文件默认只有只读权限,vim打开后,可使用q!来强制保存


关于gcc/g++的讲解就到这里,感谢大家阅读本博客,我们下一篇也将继续介绍Linux中的其他工具,我们下篇博客再见~

相关推荐
波特率1152002 小时前
bash命令进阶学习(Shell 元字符)
linux·bash·shell
Yungoal2 小时前
Visual StudioProfiler对工作流进行热点分析
c++·visual studio
Lsir10110_2 小时前
【Linux】网络编程基础—套接字
linux·运维·服务器·网络·c++
Java小白笔记2 小时前
Linux中使用systemd服务单元定时任务
linux·服务器·网络
小年糕是糕手2 小时前
【35天从0开始备战蓝桥杯 -- 补充包】
开发语言·前端·数据结构·数据库·c++·算法·蓝桥杯
夏乌_Wx2 小时前
Linux 进程间通信 IPC 总结:管道 + 信号量 + 共享内存 + 消息队列(附代码)
linux·数据结构·算法
lucia_zl2 小时前
linux收集进程性能数据
linux·运维·chrome
Byte不洛2 小时前
手写一个C++ TCP服务器实现自定义协议(顺便解决粘包问题)
linux·c++·操作系统·网络编程·tcp
无限码力3 小时前
华为OD机试真题2026双机位C卷 C++实现【日志解析】
c++·华为od·华为od机试真题·华为od机考真题·华为od机试真题-日志解析