【Linux系统编程】Linux下的编译器——gcc/g++的使用 及 动态库和静态库的认识

文章目录

  • 1. 概念
  • 2. gcc 的使用
    • 2.1 预处理(预编译)
    • 2.2 编译
    • 2.3 汇编
    • 2.4 链接
  • 3. 动态库和静态库
    • 3.1 动静态库的理解
    • 3.2 默认是动态链接,我们如何进行静态

这篇文章我们继续学习Linux中的开发工具,今天要学的是:
Linux下的编译器——gcc/g++

1. 概念

我们先来简单了解一下它们的概念:

gcc (GNU Compiler Collection) 和 g++ 是 Linux 系统上最常用的编译器。它们是 GNU 组织开发的一套开源编译器工具集。

gcc:

gcc 是 GNU 编译器集合中的 C 语言编译器。
它支持多种 C 语言标准(如 ANSI C、ISO C89、ISO C99)以及一些扩展特性。
gcc 可以将 C 语言源代码编译成可执行文件,或者生成汇编代码和目标文件。

g++:

g++ 是 GNU 编译器集合中的 C++ 语言编译器。
它在 gcc 的基础上添加了对 C++ 语言的支持,包括标准 C++ 和一些扩展特性。
g++ 可以将 C++ 源代码编译成可执行文件,或者生成汇编代码和目标文件。

gcc 和 g++ 的选项基本上都是一样的,我们这里就重点以gcc为例来进行讲解。

2. gcc 的使用

通过上面的了解我们知道gcc 和 g++ 其实就是Linux系统上的编译器。

编译器其实就是是一种将高级程序代码(如 C、C++、Java 等)转换为低级机器代码或可执行文件的软件工具。

那在之前C语言的学习阶段,我们其实有一篇文章比较详细的讲解了一下一个C程序从源文件变成可执行程序的过程

在这里插入图片描述
大家如果不太清楚或者忘了的话可以复习一下——【C进阶】——我们写的代码是如何一步步变成可执行程序(.EXE)的?
编译器做的工作其实就是对应图中的翻译环境中的几步。

那至于详细的过程,我们这里就不再展开讨论了(大家可以看之前的文章),不过我们再来结合操作简单的复习一下

之前的时候我们讲解的并没有让大家关心具体的操作,那现在,大家就需要来学习一下操作过程中的这样命令了。
我先来创建一个源文件myfile.c
在这里插入图片描述
对于这样一个源文件,如果我们直接gcc编译的话,他会直接做完整个翻译过程,自动生成一个名为a.out的可执行文件
在这里插入图片描述
我们就可以直接执行输出结果。
那其实这个可执行文件的名字我们是可以自己指定的
gcc -o 新生成文件名 原文件名
"-o"选项用于指定生成的可执行文件或目标文件的名称。
-o之后一定是加我们自己给新生成文件起的名字
在这里插入图片描述

对于程序的翻译,分为下面几个过程:

2.1 预处理(预编译)

预处理阶段主要完成头文件的展开、宏替换、条件编译和去掉注释等工作。

那上面我们演示的是从源文件直接生成可执行文件,那如果我想让它执行完预处理过程就停下来呢?

这里用到另一个选项:-E
-E:预处理之后就停下来
所以我执行gcc -E myfile.c
在这里插入图片描述
但是这样直接执行之后它会把预处理之后文件的内容直接显示到显示器上,这样不太好看。

所以我们也可以-o指定一下文件名,把它放到对应文件里

那对于预处理之后的文件,一般后缀为.i
在这里插入图片描述
首先我们可以观察到预处理之后文件大小大了很多。
然后我们可以用vim打开观察一下,当然打开myfile.c的同时我们可以借助vs 文件名同时显示myfile.i,分屏显示,对比观察一下
在这里插入图片描述
这里看到myfile.i的内容是比较多的,我们看看他又多少行
在这里插入图片描述
一共有800多行,当然这个其实我们C语言那篇文章也带大家看过,其实前面多的这么多东西就是头文件展开的内容,当然还会做一些其它动作比如注释的删除、宏替换和条件编译语句的处理等。
不过这里我们没用这么多东西。

2.2 编译

编译过程,就是把预处理之后的C语言代码转换成汇编代码

那如果我想让编译结束停下来呢?

-S:编译结束就停止
在这里插入图片描述
那这里我们看到不指定名字的话,他自动把生成的文件命名为.s后缀的(编译之后文件后缀为.s)
当然我们还可以自己指定
在这里插入图片描述
那我们打开看一下
在这里插入图片描述
那这里里面放的其实就是对应的汇编代码

2.3 汇编

汇编其实就是把汇编指令转化为二进制的机器指令,生成对应的可重定位的二进制目标文件。

那我想查看汇编之后的文件:

-c:汇编结束就停止
在这里插入图片描述
当然这个我们是看不懂的,它是一种二进制文件
在这里插入图片描述

2.4 链接

链接过程是将多个目标文件(可重定位目标文件)以及库文件组合在一起,生成最终的可执行文件。

那要链接生成可执行文件的话其实就不用选项了:

直接对汇编生成的.o文件进行gcc就可以生成最终的可执行程序

在这里插入图片描述
就可以执行了
在这里插入图片描述

把这整个过程我们又过了一遍。
在这里插入图片描述

但是,下面关于链接过程中的某些内容,我们还要来探讨一下

3. 动态库和静态库

上面说到在链接过程中我们的程序会和用到的一些库链接到一起。

大家思考一个问题,为什么我们在Linux上可以进行C/C++代码的编译链接这些动作呢?

其实其中一个比较重要的原因就是Linux提供了这些语言所需要的开发库,如标准C库(libc)、标准C++库(libstdc++)以及其他各种系统库和第三方库。这些库提供了大量的函数和工具,方便开发者编写各种类型的应用程序。
那其实我们可以看一下我们当前的Linux系统上都提供了那些库:
ls /usr/include
在这个路径下
在这里插入图片描述
我们看到里面有些头文件其实是我们比较熟悉的。

那下面我们就来学习这样一条命令:

ldd:ldd命令用于打印一个可执行文件或共享库文件依赖的动态链接库(shared library)列表。它会递归地检查可执行文件或共享库文件所依赖的其他库文件,以及这些依赖的库文件的依赖,一直到所有依赖的库文件列表打印完毕。

比如,对于我们上面生成的可执行程序,我们就可以使用ldd命令查看一下它都依赖了哪些库

在这里插入图片描述
我们看到这里打印出来有3条,不过我们重点关心一下第二个。
第二个libc.so.6其实就是Linux中的C标准库。

另外我们在安装一些ide的时候,比如就拿我用的这个vs2022来说,我们安装它的时候,其实一个比较重要的工作就是安装相关的库之类的东西。
在这里插入图片描述
就类似这个图。

在这里涉及到一个重要的概念——库(函数库)

我们的C程序中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实“printf”函数的呢?
最后的答案是:
系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能使用函数“printf”了,而这也就是链接的作用

那说到库,其实分为两种(库本质也是文件):

  1. 动态库

在Linux中,动态库一般是以lib开头,.so为后缀
即libXXXXX.so

  1. 静态库

静态库一般以lib开头,.a为后缀
即libXXXXX.a

3.1 动静态库的理解

那这里提到的动态库和静态库该怎么理解呢?

当我们谈论库(Library)时,可以将其比作图书馆,而静态库和动态库则是两种不同的图书存放方式。

想象一下,你是一名学生,图书馆中有很多有用的书籍,供你在学习过程中参考使用。

静态库(Static Library) 类似于你个人的书包,你从图书馆中选择了一些书籍,把它们拷贝到你的书包里。这些书籍是你个人拥有的,可以在需要的时候直接使用。当你需要使用这些书籍时,你只需从书包中取出,不需要依赖图书馆,也不会影响其他学生。

在编程中,静态库是在编译时将库的代码和程序代码链接在一起,形成一个单独的可执行文件。这意味着静态库的代码被复制到了最终的可执行文件中(这种链接方式我们称为静态链接),程序在运行时不需要外部的库文件依赖。这样做的好处是,程序更加独立,可以在不同的系统中运行,不受外部环境的影响。
但是生成的文件比较大。

动态库(Dynamic Library) 类似于图书馆中的共享书架,每个学生都可以访问这些书架上的书籍。当你需要使用这些书籍时,你可以从书架上取出,使用完毕后放回书架上供其他人使用。这意味着多个程序可以共享同一个动态库,减少了存储空间的占用。

在编程中,动态库是在运行时由操作系统加载的库文件,程序在运行时需要由链接器引入动态库,才能使用其中的函数或资源。可执行文件中只包含对库函数的引用或者说地址,而不复制库的代码和数据(动态链接)。这样做的好处是,多个程序可以共享同一个动态库,减少了内存的占用和可执行文件的大小。

总结起来:

静态库将库的代码复制到可执行文件中,使得程序独立运行;动态库则共享在操作系统中,减少了内存占用和可执行文件的大小。静态库适合小型独立程序,而动态库适合大型程序或多个程序共享使用。
在这里插入图片描述

3.2 默认是动态链接,我们如何进行静态

然后想告诉大家,在我们的Linux上,默认只有动态库,进行的是动态链接

之前我们学过一个file指令,它可以更清晰的显示一个文件的类型
我们执行file myfile.exe在这里插入图片描述
就可以看到里面有一个dynamically linked,它的意思就是动态链接

那如果我们想进行静态链接,能做到吗?

可以的。
不过呢,一般我们的Linux上默认只有动态库,所以,如果想进行静态链接的话,需要先安装一下静态库:
yum install -y glibc-static libstdc++-static
把指令给大家,大家直接执行就行(普通用户+sudo),这条指令是把C和C++的静态库都安装上的。

然后就可以进行静态链接了

对应的命令是
gcc -static:静态链接
在这里插入图片描述
🆗,大家看到了吗,静态链接生成的可执行文件比动态链接生成的大了好多好多。
我们也可以用file查看一下静态链接生成的可执行文件
在这里插入图片描述
里面也能看到静态链接statically linked

关于动静态库我们先了解到这里,后续还会进行更深入的学习…
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/18606.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据备份与恢复

目录 数据备份 1、备份单个数据库中的所有表 2、备份数据库中的某些表 3、备份所有数据库 4、只备份emp表结构 数据库恢复 方法1:使用mysql 命令恢复 方法2:进入数据库,使用source加载备份文件恢复 MySQL表的导入导出 数据备份 MySQLdump备份数据库语句的…

对RAM和ROM的理解

什么是RAM、ROM? RAM(Random Access Memory)随机存取存储器 ROM(Read Only Memory)只读存储器 先记住一件事 RAM断电将失去数据 ROM断电仍会保留数据 RAM、ROM、Flash、内存条、硬盘、SD卡到底怎么归类? 我们先来看下计算机的原理和计算机的需求 …

国网技术学院MySQL课堂练习

一、数据库的安装和配置 在虚拟机中安装WINDOWS7操作系统 正常安装,查询安装教程即可安装必备组件和MYSQL5.7数据库 正常安装,查询安装教程即可修改my.ini配置文件中关于character_set的相关设置 直接补下面的代码即可,作用为设置默认的内…

SpringBoot集成Flowable工作流

SpringBoot集成Flowable工作流 Flowable是什么?一、添加依赖二、flowable配置三、定义流程文件1.使用流程文件定义工作流2.idea使用插件来定义流程图1.安装插件2.创建bpmn文件并画流程图3.右击流程用模型设计器打开文件 四、测试controller Flowable是什么&#xff…

数据结构 - 线性表(C语言版)

线性表分为顺序表和单链表 线性表的操作主要是查询、插入、删除 1、顺序表 首先,定义一个顺序表的结构体 #define MAX_SIZE 10 typedef struct {int data[MAX_SIZE];int length; }SqList, * PsqList;创建一个顺序表 //创建顺序表 void createSqList(PsqList pSq…

【Excel】csv乱码

原因 CSV用UTF-8编码 Excel用ANSI编码 解决 1 创建一个新的Excel 2 数据 > 从文本/CSV 3 选择文件 4 选择 文件原始格式 和 分隔符 (根据自己文件进行选择,如果不知道编码,可以一个一个的试,直到不出现乱码)

CCLINK转MODBUS-TCP网关cclink利modbus区别

大家好,今天我们要聊的是生产管理系统中的CCLINK和MODBUS-TCP协议,它们的不同使得数据互通比较困难,但远创智控YC-CCLK-TCP网关的出现改变了这一切。 1, 远创智控YC-CCLK-TCP是一款自主研发的CCLINK从站功能的通讯网关&#xff…

Blender初学者入门:做一个魔方

文章目录 安装和使用基本操作物体属性材质 安装和使用 由于Blender是开源免费的,所以可直接在官网下载,正常安装,没有坑点。 在打开Blender后,创建新文件,选择General,就会得到一个立方体,而界…

hadoop -Unable to start failover controller. Parent znode does not exist

Unable to start failover controller. Parent znode does not exist 问题描述 今天使用星环的TDH集群时,HDFS服务宕掉,在后台查看namenode 始终起不来 kubectl get pod -o wide | grep hdfs 如上图,k8s pod 起来又crash 掉,然后…

手机外壳缺陷视觉检测软硬件方案

单独使用一种光源效果图 同轴光会出现亮度不够的情况;回形面光因为光源中间的圆孔会使图像有阴影,造成图像效果不均衡,所以不采用单独光源打光 使用同轴回形面光源效果图 回形光源照亮产品要寻找的边缘,同轴光源起到补光的作用&a…

【学会动态规划】第 N 个泰波那契数(1)

目录 动态规划怎么学? 1. 题目解析 2. 算法原理 1. 状态表示 2. 状态转移方程 3. 初始化 4. 填表顺序 5. 返回值 3. 代码编写 4. 空间优化 写在最后 动态规划怎么学? 学习一个算法没有捷径,更何况是学习动态规划, 跟…

vue2 若依项目,使用plotly.js-dist图表库,将数据图表一键导出为图片

此代码适用的场景是一个页面有多个数据图表。 首先需要拿到你生成数据图表的数据, 然后赋值给一个数组,数组需要在data定义,还需要去重。 // 检查是否有相同的parameter值const hasDuplicate this.toImageArr.some(iiem > iiem.paramete…