Linux工具学习之【gcc/g++】

news2025/1/17 6:18:00

✨个人主页: Yohifo
🎉所属专栏: Linux学习之旅
🎊每篇一句: 图片来源
🎃操作环境: CentOS 7.6 阿里云远程服务器

  • Whatever is worth doing is worth doing well.

    • 任何值得去做的事情,都值得把它做好。

    向阳而生


文章目录

  • 📘前言
  • 📘正文
    • 📖gcc/g++ 命令
      • 📃-o 目标文件
      • 📃-E 预处理
      • 📃-S 编译
      • 📃-c 汇编
      • 📃gcc 链接
      • 📃小结
    • 📖库
      • 📃动态库
      • 📃静态库
      • 📃优劣比对
    • 📖自动化构建工具
      • 📃Makefile 文件
      • 📃make 指令
      • 📃任务刷新策略
      • 📃.PHONY 伪目标
      • 📃补充
    • 📖sudo 提权
  • 📘总结


📘前言

书接上文,我们已经学习了 Linux 中的编辑器 vim 的相关使用方法,现在已经能直接在 Linux 中编写C/C++代码,有了代码之后就要尝试去编译并运行它,此时就可以学习一下 Linux 中的编译器 gcc/g++ 了,我们一般使用 gcc 编译C语言,g++ 编译C++(当然 g++ 也可编译C语言),这两个编译器我们可以当作一个来学习,因为它们的命令选项都是通用的,只是编译对象不同。除了编译器相关介绍外,本文还会库、自动化构建工具、提权等知识,一起来看看吧
gnu、gcc


📘正文

📖gcc/g++ 命令

在接下来的学习中,我们以 gcc 为例,因为两者选项都是通用的,所以也就相当于间接学习了 g++ ,这个编译器上手还是很简单的,选项也不是很多

注意: 如果命令失效,很有可能是没有下载 gcc/g++ ,需要自行下载安装 gccg++

📃-o 目标文件

gcc 源文件 默认会将代码编译链接并生成可执行文件 a.out ,当然前提是代码没问题,所以这样看来编译一个文件还是很简单的

$ gcc 源文件	//直接编译源文件,生成默认可执行文件为 a.out

直接 gcc
可能有的人不想让它生成默认的 a.out ,想生成为指定文件,没有问题,直接通过 -o 选项就能实现
注意:-o 选项后面必须紧跟生成的目标文件,这个选项可以放在源文件后面,也可以放在前面

$ gcc test.c -o OK	//编译生成文件为 OK
$ gcc -o OK test.c	//这种写法也是可以的

指定编译
在我们使用 gcc/g++ 时,都可以通过 -o 选项生成指定文件

📃-E 预处理

在C语言学习阶段,我们学习了源文件变成可执行文件的过程,即预处理-编译-汇编-链接,当时因为没有学习Linux,没法很好的展示各个环节的现象,今天可以来详细看看

首先是第一步:预处理,又称预编译

  • 会进行头文件展开、删除注释、替换宏、执行条件编译等操作
  • 目的是生成一个纯粹的C代码程序
  • 经过预处理后的文件后缀为 .i

我们可以直接通过 gcc 中的 -E 命令,使编译器在执行完预处理后停下来,配合 -o 生成指定文件,这样我们就可以观察到上面所提到的这些现象了

$ gcc -E test.c -o test.i	//预处理后的文件后缀为 .i 此时仍然是C语言

预处理阶段
预处理就像是过滤,会把代码进行检查删除,留下纯粹的C代码,方便后续进行转换

📃-S 编译

下面进入第二个步骤:编译

  • 进行语法分析、词法分析、语义分析、符号汇总等,然后将合法的代码转为汇编代码
  • 编译目的是生成汇编代码
  • 编译后生成的文件后缀为 .s

编译阶段比较重要的一步就是符号汇总,它会各种符号汇总起来,方便后续符号表的形成,符号表用于各种函数间的相互调用

我们可以通过 -S 选项,使 gcc 在执行完编译阶段后就停下来,配合 -o 生成文件 test.s

$ gcc -S test.c -o test.s	//可以直接从 test.c 开始执行,也可以从上一步中的 test.i 执行

编译阶段

📃-c 汇编

接下来进入第三步:汇编

  • 主要任务是将汇编代码转为二进制,并生成符号表
  • 二进制文件的格式是 elf ,此时 vim 查看为乱码
  • 生成的文件后缀为 .o

因为计算机只能看懂二进制,所以将代码转为二进制是必须进行的操作,除此之外,还有一个重要步骤:生成符号表

关于符号表

  • 这个东西相当于函数独一无二的地址,在Linux 中,C语言的符号表比较简单,通常是 _函数名,比如 _Add ;C++更详细一些,通常为 _Z函数名长度+函数名+参数1+参数2 ,比如常见的 Add 函数,生成的符号表为 _Z3Addii ,这里的参数是两个整型,这也是C++支持重载,而C语言不支持重载的根本原因,毕竟C语言中两个重名的函数生成的符号表是完全一样的,区分不了

可以通过 -c 选项使 gcc 在执行完汇编阶段后就停下来,指定保存文件为 test.o

查看生成的 test.o 文件,可以用 readelf 这个工具,缺失的可以去下载

$ gcc -c test.c -o test.o	//从源文件重新开始编译,生成 test.o 二进制文件
$ gcc -c test.s -o test.o	//从上一步中生成的 test.s 文件开始编译,两者效果是一样的

//关于查看 elf 格式的文件
$ readelf -a test.o	//可以通过软件,观察到符号表等信息

汇编阶段

📃gcc 链接

下面是最后一步:链接

  • 进行合并段表、将符号表进行合并和重定位等
  • 将程序运行所需的各种函数链接起来,包括与库函数的链接,Linux 中一般是动态链接,链接后生成可执行文件,此时的文件也是 elf 的格式
  • gcc 默认生成的可执行文件为 a.out,我们可以指定生成任意文件
$ gcc test.c -o myfile	//生成可执行文件为 myfile
$ gcc test.o -o myfile	//继上一次生成的二进制文件执行链接,也是没有问题的

链接阶段
以上就是本文关于 gcc/g++ 的全部内容了

📃小结

关于各个命令选项可以巧记为 ESc 这是键盘上的一个键,忘记了可以看看
还有各个选项对应生成的文件后缀为 iso

下面还会介绍程序相关链接情况


📖库

众所周知,每种编程语言都有属于自己的库,比如我们C语言中的 stdiostringstdlib 等等标准库,当我们程序在调用库函数时,就是在调用标准库中的函数,而这些标准库都在 /usr/include 这个目录中,这个文件就是 Linux 中的C语言动态库;除了 动态库 外还有 静态库

动态库

📃动态库

动态库 即通过 动态链接 的库,动态库 又称 共享库,因为 动态库 中的内容是被所有程序共享的,简言之 动态库 中的代码只需要存在一份,程序需要使用时,直接通过对应位置调用就行了

Linux 中默认使用 动态链接 的方式,我们可以通过指令 ldd 最终生成的文件 来查看最终生成文件的链接情况

$ ldd 最终生成的文件	//查看文件的链接情况

链接情况

libXXX.so 是动态链接的标志

  • 其中 lib 是前缀
  • .so 是后缀
  • 去掉前缀与后缀,就是最终调用的库

举例:libc.so 去掉前缀与后缀,最终为 c ,可以看出文件最终调用的是C语言共享库,即 动态链接

动态链接 主要依赖不同函数在库中的位置信息进行调用,只有一份代码库,比较节省空间

我们还可以通过 file 命令查看文件详细信息

$ file 最终生成的文件	//查看文件的详细情况

查看详细信息
这也验证了 Linux 默认使用 动态链接 的现象

类比记忆

  • 动态库 就像是网吧(假设只有一家),那么全校的同学都可以去网吧中上网,还可以根据自己的喜好选择自己喜欢的机位,当然前提是你知道在哪个位置

动态库

📃静态库

除了 动态库 外,还有 静态库 ,采用 静态链接 的方式;静态链接 不同与 动态链接 共享的方式,如果程序调用 静态库 ,会将自己所需要的代码 拷贝至程序中 ,完成拷贝后,后续不需要再调用 静态库

如果想采用 静态链接 链接的方式编译程序,需要在编译时加上 -static 选项,当然前提是得有 静态库,没有的可以通过 yum install -y glibc-static 下载 静态库

当然我们也可以通过 ldd 最终生成的文件 查看是否为 静态链接

$ yum install -y glibc-static	//下载静态库
$ gcc test.c -o myfile-static -static	//采取静态链接的方式编译程序
$ ldd 最终生成的文件	//查看文件的链接方式

静态链接
静态库 命名为 libXXX.a

  • lib 是前缀
  • .a 是后缀
  • 去掉前缀与后缀,就是最终调用的库

我们也可以采用 file 命令查看详细信息

$ file 文件	//查看详细信息

查看静态链接
静态链接 因为是直接将需要的代码拷贝到程序中,因此最终生成的文件会变大,比较占空间

大小
因为这种方式很占空间,所以 Linux 中默认使用 动态链接 的方式

类比记忆

  • 静态库 就像是把网吧里的电脑,买了一台同款的在自己寝室(调用某个函数),一台还好,如果买了很多台,寝室自然就没有空间了

📃优劣比对

动态库静态库 各有优缺点,不然也不会同时存在两种库了

区别动态库静态库
调用方式通过函数位置进行调用直接将需要的函数拷贝至程序中
依赖性(运行时)需要依赖于动态库可以独立于静态库运行
空间占用共享动态库中的代码,空间占用少拷贝代码会占用大量空间
加载速度调用函数,加载速度慢直接运行,加载速度快

小结
动态库

  • 优点
    • 可以实现不同进程间的资源共享
    • 对于函数的升级只需要替换动态库文件,不需要重新编译程序
    • 可以控制是否加载动态库,不调用函数时就不加载
  • 缺点
    • 需要调用函数,加载速度较慢
    • 程序运行需要依赖动态库

静态库

  • 优点
    • 所需函数直接拷贝至程序中,运行速度快
    • 程序运行无需依赖库,便于移植
  • 缺点
    • 对于函数的升级,需要重新进行编译
    • 同一份代码可能出现重复拷贝的情况,浪费空间

📖自动化构建工具

自动化构建工具可以帮助我们完成设置好的指令,指令为 make ,我们可以通过提前设置,实现源文件的快速编译

📃Makefile 文件

要想使用 make 指令,就得先有 Makefile 文件,Makefile 文件中主要编写任务,而任务由 依赖关系 + 依赖方法 构成

1.依赖关系

  • 比如源文件为 test.c ,编译后生成的文件为 myfile ,那么两者间的 依赖关系myfile:test.c 这组 依赖关系 我们可以写入 Makefile 文件中

2.依赖方法

  • 有了关系后,就要描述具体实现方法,比如上面那组 依赖关系依赖方法gcc test.c -o myfile依赖方法 也写入 Makefile 文件中

编写 Makefile

完成上面两个内容的编写后,我们就得到了一个基本的自动化任务,输入 make myfile 即可编译 test.c 文件,生成 myfile

$ make myfile	//执行自动化指令,编译 test.c 文件

执行make指令

注意: 同一个自动化任务,执行成功后,如果相关文件最近没有发生改变,那么无法再次执行自动化任务

📃make 指令

上面展示了如何编写 Makefile 文件并执行相关任务,使用了 make file 指令,并没有直接使用 make指令,因为这个指令还是有些说法的

单纯输入 make 指令时,默认执行 Makefile 中的第一个任务,当任务成功执行后,不再继续执行后续任务(一个 Makefile 文件中,可以有多个任务),由此可见,单纯的 make 指令只会执行第一个自动化任务

单纯的make
当我们编写好 Makefile 文件后,可以通过 make 任务名 调用任务,任务名就是 依赖关系 中的左侧名;也可以直接通过 make 调用第一个任务

📃任务刷新策略

前面说过,同一个方法如果成功执行过,在原文件最近修改时间没有发生变化时,无法再执行任务,这背后的原因是方法是否执行会先判断生成的目标文件是否为最新,如果为最新,就不再执任务

举例:重复执行 make myfile 任务

$ make myfile	//第一次执行任务,成功
$ make myfile	//第二次执行任务,失败,因为源文件最近没有被修改

刷新策略
想要再次执行任务也很简单,对源文件做出修改,或者直接 touch 一下源文件就行了,两种行为都会修改文件的最近修改时间,使源目标文件不是最新时间

📃.PHONY 伪目标

.PHONYMakefile 文件中的一个关键字,意为对某某对象生成伪目标,这样就能在不对源文件进行修改的情况下,重复执行任务了

//Makefile 文件中
.PHONY:myfile

.PHONY
在使用关键字 .PHONY 对目标进行修饰后,可以无视任务刷新策略,重复执行任务了

不过这有什么意义呢?
答:对于这种源文件来说,没有任何意义

.PHONY 这个关键字,一般是用来修饰 clean 任务,即清理解决方案,Makefile 实现为

//Makefile 文件内
.PHONY:clean
clean:
	rm -r myfile

清理

换个角度想想,当我们把生成的原目标文件清理后,再执行任务,生成目标文件是一件很合理的事,也完全符合任务刷新策略

由此来看,.PHONY 也是很有用的

注意: clean: 这种半缺失 依赖方法 是合理的,毕竟清理这个任务也不需要任何对象,只需要单纯的执行删除(清理)指令就行了

📃补充

make 指令的工作原理是去 Makefile 文件中寻找任务执行,它的设计者为了确保普适性,创建 makefile 文件也是合法可用的

也就是说,我们创建 make 指令的任务源文件时,可以创建为 Makefile ,也可以创建为 makeile


📖sudo 提权

权限,是一个让人又爱又恨的东西,它的安全性固然很重要,但有时候又太麻烦了,当我们普通用户想执行操作时,需要请 root 出马,比如最基本的下载软件指令,感觉有些小题大做了

为了解决这种不合理的现象,Linux 中就有 sudo 提权 这个概念,简单来说,就是暂时借助 root 的身份去完成某条指令

$ sudo yum install -y sl	//暂时提权下载软件

sudo 提权
怎么样?感觉很爽吧?
不过普通用户默认是没有赋予提权权限的,还是需要请 root 帮忙配置
步骤如下

  • 切换为 root 用户
  • 打开 /etc/sudoers 这个文件
  • 找到如下图所示区域,将需要提权的普通用户添加进去就行了

提权

//root 身份下
# vim /etc/sudoers	//打开这个配置文件,找到上图区域进行修改就行了

提权 配置完成后,普通用户遇到权限拒绝的场景时,只需要 sudo 指令 ,然后输入当前普通用户的密码,就可以暂时借助 root 的身份无视权限完成指令了

注意: sudo 后,输入的是当前普通用户的密码,不需要输入 root 密码,这样就能做到保护 root 的情况下,执行指令了


📘总结

以上就是关于Linux工具:gcc/g++ 的全部介绍了,gcc/g++ 是一款优秀的编译器,它不仅可以编写C/C++ 代码,得益于强大的 GNU,它可以编写 绝大多数的后端语言代码(当然前端无缘,毕竟全是命令行);我们还学习了 的相关知识,知道了 动态库静态库 的优缺点,还能通过 make 指令执行自动化任务,再配合上 sudo 提权,可以让我们的 Linux 开发效率大大增加

如果你觉得本文写的还不错的话,期待留下一个小小的赞👍,你的支持是我分享的最大动力!

如果本文有不足或错误的地方,随时欢迎指出,我会在第一时间改正

星辰大海

相关文章推荐
Linux 权限理解和学习 (热榜文章,推荐食用)
Linux工具学习之【vim】(学习本文的必备文章)
听说Linux基础指令很多?这里都帮你总结好了

感谢支持

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

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

相关文章

SpringBoot中使用Swagger详解

在Spring Boot中规范的使用Swagger进行接口测试 文章目录Swagger是什么?为什么要用Swagger?准备工作创建项目编写接口验证高级配置文档注释接口过滤自定义响应SwaggerUI的使用遇到的问题:Swagger是什么? Swagger是一套基于OpenAP…

【Kubernetes 企业项目实战】02、基于 Prometheus 和 K8s 构建智能化监控告警系统(上)

目录 一、Prometheus 基本介绍 二、Prometheus 特点 样本 三、Prometheus 组件介绍 四、Prometheus 工作流程 五、Prometheus 和 zabbix 对比分析 六、Prometheus 的几种部署模式 6.1 基本高可用模式 6.2 基本高可用 远程存储 6.3 基本 HA 远程存储 联邦集群方案…

Word文档内容如何添加双删除线

我们有时需要在Word里面添加双删除线,那么怎么添加呢?看看小编是怎么操作的吧。 首先,运行speedoffice并打开Word文件,选中需要添加双删除线的内容; 然后,点击鼠标右键,在右键菜单中选择“高级…

如何搭建云进销存-采购管理系统?

1、简介 1.1、案例简介 本文将介绍,如何搭建云进销存-采购管理。 1.2、应用场景 云进销存-采购管理应用支持多种商品特性管理,灵活适配不同主流行业商品管理要求,并可通过报表追溯查询,实现差异化的品类管理及分析。 2、设置…

【Linux】-- 进程终止进程等待

目录 深入理解fork 进程终止 进程常见退出场景 退出码 总结 进程等待 进程等待必要性 wait与waitpid 阻塞等待 非阻塞等待 总结 深入理解fork 在linux中fork函数时非常重要的函数,它从已存在进程中创建一个新进程。新进程为子进程,而原进程为…

Rhce第三次作业

1. 基于同一IP的不同端口访问不同的网站(可以通过域名去访问)ipport1 -> 对应一个域名ipport2 -> 对应一个域名使用域名1我应该访问到 ipport1对应的内容使用域名2我应该访问到 ipport2对应的内容/etc/hosts文件下写入ip和域名,进行域名解析写入192.168.137.1…

vue3学习笔记之TransitionTransitionGroup

文章目录Transition&TransitionGroup动画组件1. Transition1.1 Transition API1.2 基于CSS的过渡效果自定义过渡class Animate动画库同时使用 transition 和 animation深层级过渡与显式过渡时长duration(总持续时间)1.3 JavaScript 钩子 GreenSock…

FPGA知识汇集-GPGPU与FPGA

虽然FPGA的功能很强大,但是并非所有的设计都会使用到这样的芯片。很多系统架构师在开始的时候会斟酌到底是使用FPGA还是其他的代替方案,例如GPGPU(通用的图形处理单元)。 由于GPGPU特有的架构和处理能力,在很多现代的设…

SpringBoot+VUE前后端分离项目学习笔记 - 【20 权限菜单 上】

数据库 新建sys_role角色表 与sys_menu菜单表 CREATE TABLE sys_role (id int NOT NULL AUTO_INCREMENT COMMENT id,name varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 名称,description varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 描述…

【C++】list模拟实现

看源码观察结构 由源码可以得知,list的底层是带头双向循环链表 — 结点类模拟实现 list实际上是一个带头双向循环链表,要实现list,则首先需要实现一个结点类,而一个结点需要存储的信息为:数据、前驱指针、后继指针 而对于该结点类的成员函数来说,我们只需实现一个构造函数即…

Linux磁盘根目录扩容

Linux磁盘根目录扩容 1.输入命令:df -hl 红色框标记的呢就是服务器的主目录,我们能看到总容量17G ,已使用2.1G 可用15G 我们要扩张磁盘空间的就是挂载点为:/ (的这个) 2.查询磁盘分区 命令:fdisk -l 我们找到/dev/sdb 这个磁盘名称就是…

Linux常用命令——nethogs命令

在线Linux命令查询工具(http://www.lzltool.com/LinuxCommand) nethogs 终端下的网络流量监控工具 补充说明 有很多适用于Linux系统的开源网络监视工具。比如说,你可以用命令iftop来检查带宽使用情况。netstat用来查看接口统计报告,还有top监控系统当…

CMake快速入门

介绍 之前讲的Makefile的配置跟你当前的系统非常强的相关,例如在Linux或苹果下配置完Makefile,放到Windows下就会有问题,因为编译器会不同、路径会不同等。 如果要做跨平台的软件,要给不同的操作系统,不同的编译环境…

靶机测试Connect-the-dots笔记

靶机描述DescriptionBack to the TopLevel: Beginner-IntermediateUser flag: user.txtRoot flag: root.txtDescription: The machine is VirtualBox compatible but can be used in VMWare as well (not tested but it should work). The DHCP will assign an IP automaticall…

一款兼容双系统、为代码而生的机械键盘--Keychron K3

🔥前言 从去年的9月份记得就有小伙伴发私信问我有没有值得推荐的键盘,前段时间又有几个小伙伴在发私信询问。于是我写下这篇文章去给大家推荐一款十分好用的矮轴机械键盘 > keychron K3蓝牙无线矮轴超薄机械键盘,从而让大家更好的去敲代码&#xff0c…

【PWA学习】4. 使用 Push API 实现消息推送

引言 在接下来的内容里,我们会探究 PWA 中的另一个重要功能——消息推送与提醒(Push & Notification)。这个能力让我们可以从服务端向用户推送各类消息并引导用户触发相应交互 Web Push 效果Push API 和 Notification API 其实是两个独立的技术,完全…

很好用的URL工具类

📢 📢 📢 📣 📣 📣哈喽!大家好,我是「奇点」,江湖人称 singularity。刚工作几年,想和大家一同进步 🤝 🤝一位上进心十足的【Java ToB端…

【C++】deque双端队列

目录deque的原理介绍deque的优点和缺陷deque的原理介绍 1.deque(双端队列):是一种双开口的“连续”空间的数据结构,双开口的含义是:在头尾两端都可以进行插入和删除操作,且时间复杂度为O(1)。 需要注意的是deque并不是真正连续的…

制作一个微信小程序步骤_分享个人微信小程序开发步骤

微信小程序的功能不断提高,以及用户对小程序的使用的增加,使得新一批的流量融入小程序中,越开越多的企业开始开发小程序,想要从中分一碗羹,今天内容就从如何制作一个微信小程序说起,希望对你有帮助。微信小…

Vue鼠标移入移出事件(冒泡问题)

一、定义1、mouseenter:在鼠标光标从元素外部首次移动到元素范围之内时触发,这个事件不冒泡。2、mouseleave:在位于元素上方的鼠标光标移动到元素范围之外时触发,这个事件不冒泡。3、mouseover:在鼠标指针位于一个元素…