【Linux环境基础开发工具】编译器-gcc/g++

news2024/11/15 17:15:30

写在前面:

上一篇博客, 我们学习了vim编辑工具,学会了怎么写代码,

这篇文章,我将分享代码该怎么编译的问题。

目录

写在前面:

1. gcc和g++介绍

2. gcc是如何编译程序的

1. 预处理

2. 编译

3. 汇编

4. 链接

3. gcc的选项介绍

4. 我们使用的函数是哪来的

5. 我们的.o文件和库是如何链接的?

6. debug和release        

写在最后:


1. gcc和g++介绍

我们通过gcc和g++编译代码,gcc主要编译C语言,g++则可以编译C语言和C++,

gcc和g++的选项基本一致,所以我介绍gcc的选项,g++直接平替过去就行。

这里我们话不多说,直接演示一下:

比如说,我们写了一段代码:

我们可以用gcc来编译一下:

我们发现,使用gcc编译的时候,他会生成默认叫做a.out的可执行程序文件,

其实具体是什么名称或者说后缀并不重要,能不能执行,

只取决于他有没有可执行权限,我们在权限那篇文章已经讲过了。

当然我们也可以写C++代码,C++的后缀名有不少,

可以用.cpp,不过我更习惯用.cc作为我的后缀名:

比如说我现在写了一段C++代码,用g++编译一下:

编译的使用,默认形成的可执行程序也是a.out。

补充:

g++是可以直接编译C语言的,他就直接按照C语言的形式编译。

2. gcc是如何编译程序的

1. 预处理

预处理主要干这几件事:

a. 去注释

b. 头文件展开

c. 条件编译

d. 宏替换

这是我们文件先在包含的一段代码,存在注释,头文件,条件编译和宏替换。

 我们需要使用gcc的一个选项:-E

以及一个选项 -o 指定我们形成的文件的名字。

对这段程序进行预处理操作:

我们成功形成了文件,打开看看:

我们可以看到,左边的使我们的源代码,右边是预处理之后的程序,

可以看到,预处理该干的事情都干了:

 这个就是预处理的过程,我们学习C语言的阶段应该是学习过了。

补充内容:

我们为什么能在Windows或者说Linux下进行C/C++或者其他形式的开发呢?

我们系统中一定要提前或者后续安装上,C/C++开发相关的头文件,库文件。

C/C++开发环境不仅仅指的是vs,gcc,g++,更重要的是语言本身的头文件和库文件。

所以Linux是提前给我们装好的C/C++的头文件,

那么在哪里呢?

 这个路径就是gcc,g++在Linux下默认搜索头文件的时候,搜索的路径。

我们能在这里找到我们常用的头文件。

我们可以vim一下进入stdio.h文件里面看看:

总共就是九百多行,我们刚刚展开的头文件,也是差不多这个行数。

其实他就是把这一段拷贝到了我们的源文件当中。

所以我们在下载所谓的VS2019这些编译器,选择开发包的时候,

就是在同步下载C/C++对应的头文件和库文件。 

 补充内容:

gcc是支持对文件进行文本级内容修改的,

比如说: 

我们编译的时候,定义一个RUN的宏:

 这个宏确实是定义进去了。

2. 编译

编译形成汇编代码:

这些其实就是汇编代码。 

3. 汇编

再将汇编代码转成机器可以识别的形式,

说人话就是形成二进制:

我们就能看到这些意义不明的二进制乱码了。

当然,我们也可以用一些二进制查看工具:

 可以查看一下二进制的内容:

4. 链接

最后我们就完成了:

获得了可执行程序。 

3. gcc的选项介绍

-o 选项,

我们刚刚已经对-o 选项有了一个基本的了解,

实际上,他形成的自定义的文件名我们是可以随便修改的。

这里我就不举例子了,我命名的是mytest ,你们想叫什么都行。

只要在-o 后面跟上我们的可执行程序即可。

那么,

我们对程序进行预处理的时候,使用的 -E 选项是什么意思呢?

作用:告诉gcc,从现在开始进行程序的翻译,将预处理工作做完后就不要往后走了。

那 -S 的选项又是什么意思呢?

从现在开始进行程序的翻译,将编译工作做完就停下来。

那 -c 的选项是什么呢?以此类推:

从现在开始进行程序的翻译,将汇编工作做完就停下来。

而汇编形成的test.o文件,又称为可重定位目标二进制文件,简称目标文件。

(其实Windows下的.obj文件就是目标文件)

而这个文件是不能独立执行的,需要通过链接才能执行。

最后进行gcc链接,

其实就是将可重定位目标二进制文件,和库进行链接形成可执行程序。

他们的选项:-E -S -c ,如果你记不住的话,可以看看键盘左上角的ESC键(记得c是小写就行)

4. 我们使用的函数是哪来的

比如说这段代码里的printf函数:

我们想要调用一个函数,我们使用函数名来调用,

我们需要看到函数的声明,printf这个函数的声明在stdio.h这个头文件里面,

那他的定义呢?或者说这个函数的实现呢?是谁给我们提供的?

实际上是有一个库来给我们提供方法的实现。

这里用的是C语言,所以其实就是C语言的标准库来提供实现。

我们通过这个 路径就能找到这个C语言标准库,

所以C语言标准库本质上其实就是一个文件。

而在Linux下,.so结尾的是动态库,.a结尾的是静态库。

而在Windows下:.dll后缀是动态库,.lib后缀是静态库。

一般来说,库是有自己的命名规则的:libname.so.xxx,

所以上面的libc,c就是名字,.6是他的版本。

方法的实现就是在库当中的,

库其实就是把源文件,经过一定的编译(翻译),然后打包,只给你一个文件即可。

总结:

头文件提供方法的声明,库文件提供方法的实现 + 你的代码 = 你的软件。

(不用我们重复造轮子,站在巨人的肩膀上)

5. 我们的.o文件和库是如何链接的?

有两种方法:

1. 动态链接

2. 静态链接

先说动态库,

动态库也叫做共享库,是多个程序共享的一个库,他们是构建了一种链接的关系。

比如说我们上面刚刚演示的那个C语言的库,如果我们把它删了,

那我们的这个可执行程序就无法执行:

我们用C语言写的可执行程序,默认调用的都是动态库,就都没办法执行了。

再来说静态库,

在使用静态库的时候,实际上是把静态库的内容也拷进了程序里面,

这样使用的时候就不需要通过链接去找库资源,以后也就不用依赖静态库了,

而是可以自己使用了。

现在我们写代码验证一下:

 这是我们之前直接用gcc编译出来的可执行程序,

可以看出:

在Linux中,编译形成的可执行程序,默认采用的就是动态链接 -- 要求系统提供动态库

我们使用:gcc test.cc -o mytest_static -static

使用静态链接编译一个程序,

 可以看见他没有动态链接,

我们通过 ll 查看更多信息:

可以明显看出静态链接的可执行程序体积变大了,

在Linux中,如果要按照静态链接的方式,形成可执行程序,需要添加-static选项,

也就是系统需要提供静态库才能使用。

不过我们Linux下默认只装了动态库,静态库需要自己安装。

输入:sudo yum install -y glibc-static

就能直接安装C语言的静态库。

输入:sudo yum install -y libstdc++-static

就能直接安装C++的静态库。

补充:

1. 如果我们没有静态库,能不能使用-static进行编译呢?不能

2. 如果我们没有动态库,但是有静态库,能不能直接gcc?能

gcc默认优先动态库,如果没有动态库也会用静态库编译,-static的本质:改变优先级

3. 其实我们使用的这些库,不一定是纯的全部动态或者静态链接,是混合的。 

总结:

动静态库的优缺点:

动态库是共享库,有效的节省资源(磁盘空间,内存空间,网络空间等)

静态库,不依赖库,程序可以独立运行,但是体积大,比较消耗资源。

6. debug和release        

debug版本是我们平时写的版本,release版本是上线版本,

而debug版本可以被追踪调试

那debug为啥能被调试呢?

因为在形成可执行程序的时候,添加了debug信息。

我们可以在使用gcc的时候加入 -g 选项添加调试信息:

gcc test.cc -o mytest_debug -g

 可以看见他的可执行程序也变大了一点点,

其实就是里面添加了调试信息。

这里再介绍一个指令来查看我们可执行程序二进制的构成,

来观察我们往里面添加的调试信息:

我们输入:

readelf -S mytest | grep -i debug

查看mytest的调试信息,可以观察到是啥都没有的,

而输入:

readelf -S mytest_debug | grep -i debug

我们可以直观的看到这些调试信息。 

写在最后:

以上就是本篇文章的内容了,感谢你的阅读。

如果感到有所收获的话可以给博主点一个哦。

如果文章内容有遗漏或者错误的地方欢迎私信博主或者在评论区指出~

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CPM-Bee大模型微调

CPM-Bee大模型微调 CPM-Bee简介:环境配置:应用场景:模型训练参数训练命令:推理:评估:结论: CPM-Bee 简介: CPM-Bee是一个完全开源、允许商用的百亿参数中英文基座模型,也…

关于数据库运维系统的一些思考

这是学习笔记的第 2461篇文章 前段时间整理了一下数据库运维系统的一些内容,比自己预期的要难一些。我来简单回顾下一些参考点。 一、立足当下,混沌之中梳理问题 通常我们可以会问为什么,即为什么要做数据库运维系统,但是我们先放…

决策分析——层次分析法

工程测量与经济决策方案 决策分析——层次分析法 一、描述 层次分析法的基本原理:根据问题的性质和要达到的总目标,将问题分解为不同的组成因素,并按照因素间的相互关联影响以及隶属关系将因素按不同层次聚集组合,形成一个多层次…

NUCLEO-F411RE RT-Thread 体验 (8) - GCC环境 TIM定时器的驱动移植以及基本使用

NUCLEO-F411RE RT-Thread 体验 (8) - GCC环境 TIM定时器驱动移植与基本使用 驱动移植 定时器驱动文件位于drv_hwtimer.c中,对应components层的文件位于rt-thread/components/drivers/hwtimer/hwtimer.c中。 修改Makefile,将其编译进去。 在rtconfig.h…

Xception算法解析-鸟类识别实战-Paddle实战

文章目录 项目背景一、理论基础1.前言2.设计理念2.1 多尺寸卷积核2.2 点卷积2.3 卷积核替换2.4 Bottleneck2.5 深度可分离卷积(Depthwise Separable Conv) 3.网络结构4.评估分析 二、数据预处理三、数据读取四、导入模型五、模型训练六、结果可视化七、个体预测结果展示总结 项…

BLE蓝牙模块应用|蓝牙MAC地址二维码扫描打印解决方案

在智能穿戴、智能安防领域,用户需要通过蓝牙MAC地址来完成产品与APP的绑定。为简化产品的使用和管理,厂家会采用蓝牙MAC地址二维码扫描打印解决方案,将蓝牙MAC地址打印成二维码并贴在产品的包装盒或者产品外壳上。本篇带大家了解一下蓝牙MAC地…

基于Java德云社票务系统设计实现(源码+lw+部署文档+讲解等)

博主介绍: ✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战 ✌ 🍅 文末获取源码联系 🍅 👇🏻 精…

干货 | 电力数据流通使用模式及安全指南

以下内容整理自清华大学《数智安全与标准化》课程大作业期末报告同学的汇报内容。 一、电力数据及流通简介 电力数据的流通整体环节也是它生命的全周期。 电力用户大体可以分为四类,分别是个人,工农业企业,商业建筑以及城市基建,这…

火山引擎 Dataleap 数据质量解决方案和最佳实践(一):数据质量挑战

更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群 什么是数据质量 广义上来说,数据质量的定义是数据满足一组固有特性(质量维度)要求的程度。业界通常有 6 个维度: 完…

语法降级与Polyfill:消灭低版本浏览器兼容问题

提到前端编译工具链方面,可能大家最新想到的是诸如babel/preset-env、core-js、regenerator-runtime等工具。不过,我们今天要讲的是官方的 Vite 插件vitejs/plugin-legacy,以及如何将这些底层的工具链接入到 Vite 中,并实现开箱即…

【强化学习】——Q-learning算法为例入门Pytorch强化学习

🤵‍♂️ 个人主页:Lingxw_w的个人主页 ✍🏻作者简介:计算机研究生在读,研究方向复杂网络和数据挖掘,阿里云专家博主,华为云云享专家,CSDN专家博主、人工智能领域优质创作者&#xf…

神经网络:参数更新

在计算机视觉中,参数更新是指通过使用梯度信息来调整神经网络模型中的参数,从而逐步优化模型的性能。参数更新的作用、原理和意义如下: 1. 作用: 改进模型性能:参数更新可以使模型更好地适应训练数据,提高…

python学习——pandas统计分析基础

目录 pandas统计分析基础1. Series数据2.文件读取csv文件Excel文件 3.DataFrame连接数据库读取数据库存入数据库DataFrame的属性访问DataFrame中的数据【实例1】info详细信息和describe描述统计分析【实例2】 排序【实例3】 布尔索引,条件索引【案例】修改数据 3.描…

LIBSVM与LIBLINEAR支持向量机库对模式识别与回归的可视化代码实践

支持向量机(SVM)是一种流行的分类技术。虽然提出时间到现在有70来年了,但在90年代获得了很好的发展和扩展,在人像识别、文本分类、手写字符识别、生物信息学等模式识别问题中有得到应用。然而,对于不熟悉SVM的初学者来说,往往会因…

ThreadPoolExecutor解读

目录 线程池状态 构造方法 newFixedThreadPool newCachedThreadPool newSingleThreadExecutor 提交任务 关闭线程池 其它方法 线程池状态 ThreadPoolExecutor 使用 int 的高 3 位来表示线程池状态,低 29 位表示线程数量 状态名 高 3 位 接收新任务 处理…

JavaScript ES10新特性

文章目录 导文Array.prototype.flat()和Array.prototype.flatMap()Object.fromEntries()String.prototype.trimStart()和String.prototype.trimEnd()格式化数字动态导入可选的catch绑定BigIntglobalThis 导文 JavaScript ES10,也被称为ES2019,引入了一些…

javascript被禁用怎么办?怎么启用?||如何解决javascript:void(0)的问题?

javascript被禁用怎么办?怎么启用? 有些小伙伴可能因为浏览器弹窗的凌乱而感到烦恼,想要通过浏览器禁用JavaScript的方式来避免这些广告。有些小伙伴则是因为设置了不知名的设置导致JavaScript被禁用,影响日常的使用。接下来的这…

Vue3的计算属性和监听属性

目录 computed 语法介绍 简写版 完整版 watch 介绍 监听ref式数据代码示例 监听reactive式数据 watchEffect函数 computed 语法介绍 与Vue2.x中computed配置功能一致 import {computed} from vuesetup(){...//计算属性——简写let fullName computed(()>{return per…

【kubernetes】部署kubelet与kube-proxy

前言:二进制部署kubernetes集群在企业应用中扮演着非常重要的角色。无论是集群升级,还是证书设置有效期都非常方便,也是从事云原生相关工作从入门到精通不得不迈过的坎。通过本系列文章,你将从虚拟机准备开始,到使用二进制方式从零到一搭建起安全稳定的高可用kubernetes集…

ffmpeg调整音频音量踩坑

前一阵用Flutter结合ffmpeg做了一个音视频合并功能,记录一下遇到的问题。 合并方法 首先是音视频合并命令: ffmpeg -i input.mp4 -i input.mp3 -filter_complex "[1:a]adelay0s:all1[a1];[a1]amixinputs1[amixout]" -map 0:v:0 -map "…