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

news2024/11/14 19:35:35

在这里插入图片描述
🔥博客主页 小羊失眠啦.
🎥系列专栏《C语言》 《数据结构》 《C++》 《Linux》 《Cpolar》
❤️感谢大家点赞👍收藏⭐评论✍️


在这里插入图片描述

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

文章目录

  • 程序实现的两大环境
  • 一、gcc/g++使用
    • 1.1 gcc如何完成
      • 1.1.1 预处理
      • 1.1.2 编译
      • 1.1.3 汇编
      • 1.1.4 链接
  • 二、动态库与静态库
    • 2.1 动态库
    • 2.2 静态库
  • 三、自动化构建工具
    • 3.1 Makefile文件
    • 3.2 make指令
    • 3.3 任务刷新策略
    • 3.4 .PHONY伪目标
    • 3.5 补充
  • 四、sudo提权

程序实现的两大环境

任何一个C程序的实现都要经过翻译环境执行环境

在翻译环境中又分为4个部分,预编译、编译、汇编与链接。在各个阶段主要完成的任务有:

  1. 预编译(预处理):头文件的包含、注释的删除、#define符号的替换;

  2. 编译:将C语言代码转化为汇编代码;

  3. 汇编:把汇编指令转化为二进制指令;

  4. 链接:合并符号表和段表,生成可执行程序。

在这里插入图片描述

一、gcc/g++使用

1.1 gcc如何完成

通过gcc指令的不同选项可查看各阶段所形成的文件;

格式:gcc [选项] [目标文件名] -o [生成文件名]

首先在test.c文件中写好C代码:

#include<stdio.h>

#define N 100

//#define ...

int main()
{
	int n = 0;
	printf("Hello World\n");
	printf("%d\n", n + N);
	return 0;
}

1.1.1 预处理

查看 test.c 预处理后的结果,-E选项的作用是让 gcc 在预处理结束后停止编译过程;-o 的作用是将预处理后的内容保存到test.i 文件中。

gcc -E test.c -o test.i

在这里插入图片描述

如图所示,预处理阶段进行了头文件包含、注释的删除、#define的替换。

1.1.2 编译

接下来将刚刚生成的 test.i 进行编译,并在编译之后停下来,将结果写入 test.s 中。gcc所用选项为 -S。

gcc -S test.i -o test.s

在这里插入图片描述

我们虽然可能没学习过汇编语言,但依旧隐约认识到这些就是汇编代码;可见编译阶段就是将C代码翻译为汇编指令。

1.1.3 汇编

gcc所用选项为 -c;-o 将结果写入到 test.o 中。

gcc -c test.s -o test.o

在这里插入图片描述

正如我们所见,汇编完成之后都这这样的乱码。其实汇编之后,生成的文件为二进制文件,是用来给计算机看的,咱们已经看不懂了。

1.1.4 链接

编译完成之后就进入了链接阶段,链接完成之后就会生成可执程序 mytest了。

gcc test.o -o mytest

在这里插入图片描述

但是关于链接,我们需要知道它在链接什么。

我们是否好奇过为什么我们明明没有定义过函数 printf 、return …等等的函数,但却可以使用它的功能?

其实,系统把这些函数的实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函 数 printf 了,而这也就是链接的作用。


二、动态库与静态库

函数库一般分为动、静态库两种。

2.1 动态库

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

gcc 进行函数库的链接时可选择静态链接或者动态链接

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

在这里插入图片描述

libXXX.so 是动态链接的标志

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

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

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

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

在这里插入图片描述

这也验证了 Linux 默认使用 动态链接 的现象

2.2 静态库

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

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

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

#下载静态库
yum install -y glibc-static
#采取静态链接的方式编译程序
gcc -static test.c -o Test_static
#查看文件的链接方式
ldd Test_static

在这里插入图片描述

静态库 命名为 libXXX.a

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

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

file Test_static

在这里插入图片描述

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

对比二者生成的文件大小

#采用静态链接
gcc -static test.c -o Test_static
#默认采用动态链接
gcc  test.c -o Test

若在静态链接时出错,可能是因为你的 Linux 没有安装C语言的静态库,须手动安装。

在这里插入图片描述

两种连接方式生成的文件大小几乎相差百倍。

优劣对比

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

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

小结

动态库

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

静态库

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

三、自动化构建工具

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

3.1 Makefile文件

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

1.依赖关系

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

2.依赖方法

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

在这里插入图片描述

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

#执行自动化指令,编译test.c文件
make mytest

在这里插入图片描述

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

3.2 make指令

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

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

在这里插入图片描述

在这里插入图片描述

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

3.3 任务刷新策略

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

举例:重复执行 make myfile 任务

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

在这里插入图片描述

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

3.4 .PHONY伪目标

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

//Makefile文件中
.PHONY:mytest

在这里插入图片描述

在这里插入图片描述

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

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

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

//Makefile 文件中
.PHONY:clean
clean:
	rm -r mytest

在这里插入图片描述

在这里插入图片描述

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

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

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

3.5 补充

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

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

四、sudo提权

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

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

在这里插入图片描述

不过普通用户默认是没有赋予提权权限的,还是需要请 root 帮忙配置
步骤如下

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

在这里插入图片描述

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

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

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

在这里插入图片描述

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

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

相关文章

就业班 第二阶段 2401--3.19 day2 DDL DML DQL 多表查询

在mysql库里的语句 \G 竖着排列 ; \g 横着排列 数据库用户组成 双单引号单都行 -- sql的注释 创建mysql用户&#xff1a;&#xff08;兼容5.7 8.0 &#xff09; create user root% identified by Qwer123..; grant all on *.* to root%; flush privileges; mysql 5.7 grant …

使用easyYapi生成文档

easyYapi生成文档 背景1.安装配置1.1 介绍1.2 安装1.3 配置1.3.1 Export Postman1.3.2 Export Yapi1.3.3 Export Markdown1.3.4 Export Api1.3.6 常见问题补充 2. java注释规范2.1 接口注释规范2.2 出入参注释规范 3. 特定化支持3.1 必填校验3.2 忽略导出3.3 返回不一致3.4 设置…

【单调队列】第十四届蓝桥杯省赛C++ C组 Java C组/研究生组 Python A组《子矩阵》(C++)

【题目描述】 给定一个 nm &#xff08;n 行 m 列&#xff09;的矩阵。 设一个矩阵的价值为其所有数中的最大值和最小值的乘积。 求给定矩阵的所有大小为 ab &#xff08;a 行 b 列&#xff09;的子矩阵的价值的和。 答案可能很大&#xff0c;你只需要输出答案对 998244353…

羽毛球移动步法训练

文章目录 简介训练量01 小颠步02 左右并步03 交叉步04 前后并步05 高抬腿06 高抬腿转髋07 左右移动跳08 并步跳09 前后小密步10 弓箭步跳11 开合跳参考文献 简介 本文参考&#xff1a;陈金羽毛球移动专项步法训练&#xff08;BV1cS4y1V7xA&#xff09;和颜叨叨的移动专项步法跟…

数据表练习

思维导图 面试题答问1、IO多路复用的引入目的和原理 目的&#xff1a;在有操作系统时&#xff0c;可以用多线程和进程完成任务并发执行&#xff0c;没有操作系统的情况下可以使用IO多路复用技术来进行任务并发。 原理&#xff1a;将多个阻塞任务的文件描述符统一放到一个检查容…

Qt 容器类控件

Group Box 使用 QGroupBox 实现一个带有标题的分组框可以把其他的控件放到里面作为一组&#xff0c;这样看起来能更好看一点. 核心属性 属性说明title分组框的标题alignment分组框内部内容的对齐方式flat是否是 “扁平” 模式checkable是否可选择. 设为 true&#xff0c;则在…

Golang基础知识(笔记迁移)

golang 变量作用域 局部作用域&#xff1a;代码块、函数内的全局作用域&#xff1a;顶层作用域&#xff0c;代码块外的就是全局&#xff0c;如果变量名大写&#xff0c;则改变量整个程序都可以使用。 类型断言 golang的类型断言在变量后加上.(type)&#xff0c;如果类型断言…

【Android】系统启动流程分析 —— init 进程启动过程

本文基于 Android 14.0.0_r2 的系统启动流程分析。 一、概述 init 进程属于一个守护进程&#xff0c;准确的说&#xff0c;它是 Linux 系统中用户控制的第一个进程&#xff0c;它的进程号为 1&#xff0c;它的生命周期贯穿整个 Linux 内核运行的始终。Android 中所有其它的进程…

python5:基于多进程的并发编程、基于协程的并发编程的学习笔记

进程 为什么要使用多进程&#xff1f;——GIL的存在&#xff0c;多线程实际不是并发执行 将任务分为两类&#xff1a;IO密集型&#xff08;多线程&#xff09;CPU密集型&#xff08;多进程&#xff09; 多进程的基本用法 concurrent.futures.process.ProcessPoolExecutor#进…

移除和替换任何内容:AI 驱动的图像修复工具 | 开源日报 No.204

Sanster/IOPaint Stars: 15.1k License: Apache-2.0 IOPaint 是一款由 SOTA AI 模型驱动的图像修复工具。 该项目解决了从图片中移除任何不需要的对象、瑕疵或人物&#xff0c;以及擦除和替换图片上任何内容&#xff08;由稳定扩散技术支持&#xff09;的问题。 完全免费且开…

ETH Denver 2024 精彩回顾|波卡,远不止一个区块链

ETH Denver 2024 于 2 月 23 日至 3 月 3 日在美国丹佛举行&#xff0c;该活动由 SporkDAO 主办&#xff08;SporkDAO 是一个来自美国科罗拉多州的 Web3 公益开发者组织&#xff0c;其前身或者说起源就是 ETHDenver&#xff0c;后随着组织发展逐渐转变为 DAO 开展了研究、投资等…

YOLO-v8-seg实例分割使用

最近需要实例分割完成一些任务&#xff0c;一直用的SAM(segment anything&#xff09;速度慢&#xff0c;找一个轻量分割模型。 1. YOLO-v8-seg使用 git clone https://github.com/ultralytics/ultralytics.git cd ultralytics vim run.py from ultralytics import YOLO# L…

JS加密解密之字符编码知识

在前端开发中&#xff0c;字符编码是一个至关重要的概念&#xff0c;特别是在数据传输、加密和解密等方面。JavaScript作为一种常用的脚本语言&#xff0c;在处理字符编码时也有其独特之处。本文将详细介绍JavaScript中的字符编码知识&#xff0c;包括字符编码的分类和相关案例…

【C++】1600. 请假时间计算

问题&#xff1a;1600. 请假时间计算 类型&#xff1a;基本运算、整数运算 题目描述&#xff1a; 假设小明的妈妈向公司请了 n 天的假&#xff0c;那么请问小明的妈妈总共请了多少小时的假&#xff0c;多少分钟的假&#xff1f;&#xff08;提示&#xff1a; 1 天有 24 小时&…

2_27. 移除元素

2_27. 移除元素 难度: 简单 提示: 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 元素的顺序可以改变…

知识管理入门:轻松选择合适的知识管理软件

你是不是经常觉得自己的大脑像个杂乱的仓库&#xff0c;各种信息、知识和想法在里面乱窜&#xff0c;找不到头绪&#xff1f;别担心&#xff0c;知识管理软件来帮你解决这个问题啦&#xff01;今天&#xff0c;我们就来聊聊知识管理软件这个神奇的工具&#xff0c;新手也能轻松…

python基础——语句

一、条件语句 就是 if else 语句 &#xff01; 代表不等于 代表等于if 关键字&#xff0c;判断语句&#xff0c;有“如果”的意思&#xff0c;后面跟上判断语句else 常和“if” 连用&#xff0c;有“否则”的意思&#xff0c;后面直接跟上冒号 …

华为配置WLAN 802.1X认证实验

配置WLAN 802.1X认证示例 组网图形 图1 配置802.1X认证组网图 业务需求组网需求数据规划配置思路配置注意事项操作步骤 业务需求 用户接入WLAN网络&#xff0c;使用802.1X客户端进行认证&#xff0c;输入正确的用户名和密码后可以无线上网。且在覆盖区域内移动发生漫游时&…

鸿蒙一次开发,多端部署(三)应用UX设计原则

设计原则 当为多种不同的设备开发应用时&#xff0c;有如下设计原则&#xff1a; 差异性 充分了解所要支持的设备&#xff0c;包括屏幕尺寸、交互方式、使用场景、用户人群等&#xff0c;对设备的特性进行针对性的设计。 一致性 除了要考虑每个设备的特性外&#xff0c;还…

vue3 reactive丢失响应式

问题 使用 reactive 构造响应式对象时&#xff0c;当对其进行重新赋值后&#xff0c;会导致原有变量失去响应式&#xff0c;页面不会发生联动更新 例如&#xff1a; 1、使用 reactive 定义一个响应式的对象变量 let data1 reactive({name: 小李,date: 2024-03-18,address: xx…