【Linux系统】—— 编译器 gcc/g++ 的使用
【Linux系统】—— 编译器 gcc/g++ 的使用
- 1 用 gcc 直接编译
- 2 翻译环境
- 2.1 预处理(进行宏替换)
- 2.2 编译(生成汇编)
- 2.3 汇编(生成机器可识别代码)
- 2.4 链接
- 2.5 记忆小技巧
- 2.6 编译方式
- 2.7 几个问题
- 2.7.1 如何理解条件编译
- 2.7.2 为什么编译器要先将代码翻译成汇编语言
1 用 gcc 直接编译
我们平时学的 C/C++ 代码,都是文本文件,但是我们知道计算机只认识二进制,因此我们需要将C/C++代码翻译成二进制文件
在 Windows 系统中,编辑代码和翻译过程我们都是用 VS
进行的,因为 VS 是集成的IDE环境,那么在 Linux 中我们又该如何完成代码的翻译工作呢?
在 Linux 中,我们用到的编译器是 gcc/g++
,其中gcc
是对C语言
进行编译,g++
是对C++
进行编译。因为 gcc 和 g++ 的指令操作等完全一样,本文主要是用 gcc 进行演示。
我们创建一个 test.c 文件,写上代码:
#include<stdio.h>int main()
{printf("hello world\n");printf("hello Linux\n");return 0;
}
如何用 gcc 对代码进行编译呢?
指令如下:
「gcc」 「要编译的文件」
gcc 会默认生成一个叫 a.out
的可执行文件
那如果我想指定生成文件的名字呢?
有两种方法
「gcc 」「要编译的文件」 「-o」 「目标文件」
「gcc 」 「-o」 「目标文件」「要编译的文件」
但是,仅仅学会指令是远远不够的,我们学习 gcc/g++ 更重要的是学习翻译过程背后的过程,我们知道,我们写的 C语言 代码最终要形成可执行程序,要经过预处理
、编译
、汇编
、链接
这几个过程,下面我们通过 gcc,进一步认识这四个过程。
2 翻译环境
2.1 预处理(进行宏替换)
预处理阶段主要处理那些源文件中 # 开始的编译指令。比如:# i n c l u d e include include,# d e f i n e define define,处理的规则如下:
- 将所有的 # d e f i n e define define 删除,展开所有的宏定义
- 处理所有的条件编译指令,如:
#if
、#ifdef
、#elif
、#else
、#endif
- 处理 # i n c l u d e include include 预编译指令,将包含的头文件的内容插入到该预编译指令的位置。这个过程是递归进行的,也就是说被包含的头文件也可能包含其他文件。
- 删除所有注释
- 添加行号和文件名标识,方便后续编译器生成调试信息等
我们创建一个code1.c文件、写一段代码
这一小段代码,头文件、宏定义、注释以及条件编译都有了,正好可以看看预处理的效果。
我们如何看到预处理后的结果呢?我们来学一个选项 「-E 」
- 「-E 」:进行程序翻译,在预处理做完时停下来
指令如下:
「gcc 」「-E 」「要编译的文件」 「-o」 「目标文件」
注:预处理后的文件后缀为.i
我们用 vim 打开 code.i
来看看
- 我们发现注释不见了
- 我们定义的宏M和N,预处理后也消失不见了,M直接别替换成100,这叫做宏替换
- 并且
printf("hello N\n")
和printf("no N\n")
只剩下了printf("hello N\n")
。这是因为条件编译,我们定义了N(定义了就行,可以不写值),所以预处理后保留了printf("hello N\n")
- 为什么我们的文件变大了呢?根本原因就是头文件展开。 在编译的时候,只要预处理完了,头文件就可以不需要了。头文件展开的意思就是把你要包含的头文件全部拷贝至你的目标文件里,形成
.i
文件。这不过这个 .i 文件我们现在将其打印出来并且写到文件里了,如果不写的话它就是内存级的,在编译器内部。同时 <stdio.h> 头文件中也包含其他的头文件,因此它会类似递归式的拷贝
。
因此一个你可能只写了几百行的代码,预处理后可能有上千行。
我们 C语言 用到的众多头文件,在系统中默认都是安装了的,一般是存在 /usr/include
路径下
如:我们包含的头文件 <stdio.h> 一般是存在/usr/include/stdio.h
路径下
可以用 vim 打开来看看
里面的代码近 900 行,但是它有条件编译,同时 <stdio.h> 中本身也包含了其他的头文件。
这里,我问大家一个问题,预处理后的 code1.i
还是 C语言 吗?
答案:还是C语言
不过他是一个已经预处理过,是一个干净的C语言了。
2.2 编译(生成汇编)
编辑:将C语音翻译成汇编语言
编译过后,生成的汇编文件后缀为 .s
需要用到命令行选项 「-S 」
- 「-S 」:从现在开始进行程序翻译,在编译步骤做完时停下来 指令如下:
「gcc 」「-S 」「要编译的文件」 「-o」 「目标文件」
我们可以从 .c 到 .s 也可以从 .i 到 .s,因为之前已经做过 .c 到 .i 了,就不再重复做预处理步骤, 直接 .i
到 .s
我们用 vim 打开 code1.s
2.3 汇编(生成机器可识别代码)
汇编是指通过汇编器将汇编代码转变成机器可执行的指令,每一个汇编语句几乎都对应一条机器指令。就是按照汇编指令和机器指令的对照表一一的进行翻译,也不做指令优化。
先直接上指令
「gcc 」「-c 」「要编译的文件」 「-o」 「目标文件」
如:
gcc -c code1.s -o code1.o
- 「-c 」:从现在开始进行程序翻译,在完成汇编后停下来
以 .o
为后缀的文件全称叫:可重定位目标文件,也就是我们所说的目标文件。目标文件在 Windows 系统下是以 .obj
结尾的
目标文件是二进制文件,因此我们打开它是啥都看不懂的
虽说 code1.o
已经是二进制文件,但是它还是无法被执行的。因为目标文件仅仅是将我们自己写的代码编成二进制了,可我们的程序中还包含着许多库方法,如printf、scanf、STL容器,此时我们的程序还没有和库方法关联起来,比如我们用了 printf 方法,可我们根本没有 printf 方法的实现,所以我们的目标文件是跑不动的。
所以我们的程序还要经过最后一步:链接,才能形成可执行文件
2.4 链接
链接过程没有命令行选项
指令如下:
gcc code1.o -o code1
这里我们并没有指定去链接哪个库,因为我们现在的代码里没有使用任何的第三方库,我们用的都是C语言标准库的方法,gcc会帮我们去系统里找我这个程序用了 C语言 的哪个标准库。但如果我们要依赖某个第三方库,就需要指定去链接了,这点我们以后再介绍。
生成可执行序后,程序就可以运行了
2.5 记忆小技巧
好像预处理、编译、汇编这三步的命令行选项很难记?有什么记忆方法吗?
他们分别是 「-E 」「-S 」「-c 」
合起来就是键盘左上角的「esc」键,我只需要记住前两个是大写的就行了。
而预处理、编译、汇编这三步生成的文件后缀又怎么记呢?
他们分别是『.i』『.s』『.o』
连起来就是iso,我们可以记ios,再将后面两个反过来
2.6 编译方式
一般我们在编译文件时,不会像上面一样 .i
、.s
、.o
全部生成一遍,上述这样做只是为了然我们了解整个翻译的过程。
我们编译文件的习惯是将所有的文件生成 .o 文件,再将所有相关的 .o 文件一起打个包生成可执行文件
为什么喜欢这么做呢?
主要原因是:
- 编译器在编译时,不仅仅要形成可执行程序,还可能要形成库(所谓的库其实就是把
.o
文件了个包),如果要形成库的话就不需要编译性成可执行程序 - 我们目前使用的 VS 最终就形成一个可执行程序,但往往实践中可能形成 10 个、100 个可执行程序,可能你有 1000 个源文件,其中 100 个形成程序A、50 个形成程序B、60 个形成程序C……我们需要将所有的 .o 做自由组合,形成多个可执行。在编译角度,我们可先将你们全部变成
.o
,最后如何形成可执行,再自己做组合
为什么要有链接步骤呢?
这是因为我们要站在巨人的肩膀上。
例如我们要用到的输入输出函数,要是自己来写的话那太费劲了,每做一个项目都要自己先敲一个函数出来,而且写出来也不够好,容易出问题。因此C语言将最基本的功能给我们全部开发好,再打成包,这个包就是库
。
解下来我们写代码时,我们只需要将自己的代码编译好,和C语言标准库链接形成可执行就行
有小伙伴可能会问:预处理时不是已经展开头文件了吗?为什么还要链接呢?
预处理展开的仅仅只是声明
,因为头文件时公开
的。
其实我们包的头文件源代码都是公开的,只有声明没有实现
,实现在对应的同名 .c
文件里。.c 文件 C语言 没有给你暴露出来,直接编成库了。
要最终形成可执行,重要的是方法
,而链接就是将方法找到
当然,上述讲的只是一般情况,你要是不喜欢也可以一次就形成可执行文件
2.7 几个问题
2.7.1 如何理解条件编译
我们创建 code.c 文件,写下如下代码
根据我们前面的知识,我们知道此时我们并没有定义M,执行的应是printf("社区版/免费版 version1\n")
语句
我们执行一下看看
gcc 编译时支持我们用 「-D 」 来进行命令行级别对指定源代码进行动态添加宏
如:
定义加写值
- gcc
gcc code.c -o code.exe -DM=1
只定义不写值
- gcc
gcc code.c -o code.exe -DM
gcc不用「-D 」选项定义宏它又会变成免费版
gcc这合理吗?其实是合理的
gcc编译器进行编译时第一步就是预处理,预处理的本质其实就是 让编译器编辑(修改)我们的代码! 既然预处理时,编译器能去注释,能进行宏替换,那么编译器将命令行中的 -DM
解释成 #define M
,并将其当做字符串插入到我的代码当中不过分吧。
「-D 」相当于在命令行给代码定义宏
相信对条件编译大家都能理解,大家不理解的是条件编译的用途。下面我们简单来了解一下条件编译的应用场景
-
对一款软件通过专业读、收费标准等进行区分,使用条件编译,进行代码的动态裁剪:
我们平时看到的某些软件,像VS、Xshell等,往往都分为专业版和社区版(收费版和免费版)。他们两者的区别主要是在功能方面,比如收费版支持100个功能,而免费版只支持50个功能。
这些软件也都是程序员开发的,那么程序员在维护这款软件需要维护几份源代码呢?毕竟这款软件有两个版本。
事实上,如果将同一款软件的免费版和收费版当成两个项目来看,那么公司就需要有两套班子,但其实他们功能上无非就是收费版上做一下功能的裁剪就是免费版。
所以在公司内部我们只需要维护一份源代码即可,最终在发布的时候只需要告诉别人编译这个代码时,编译成免费的还是收费的。怎么才能做到这点呢?我们可以将软件中的功能拆分一下:公共都有的放在一个模块里,需要收费的放在一个模块里,最后用条件编译将其维护起来。
这样一份代码通过条件编译就能对其进行裁剪,从而实现对内只需维护一份源代码,对外实现多份版本的目的。 -
Linux 内核源代码也是采用条件编译进行点裁剪
我们的 Linux 内核,编译好了其实体积还是很大的,但有些功能在很多的小型设备上:嵌入式设备、智能家电等,上面根本就不需要Linux支持那么多功能,这时就可以用条件编译实现代码的动态裁剪
当然,条件编译的功能远远不仅于此,但大多应用场景离我们现在的水平太远,感兴趣的小伙伴可以自行深入了解。
2.7.2 为什么编译器要先将代码翻译成汇编语言
C语言翻译成二进制指令相信大家都能理解,因为机器只认识二进制。但为什么编译器要先将C语言翻译成汇编语言,再将汇编语言翻译成二进制呢?
为什么计算机只认识二进制
简单来说是因为 0 和 1 是最简单的硬件电路,简单就意味着可靠,计算机通过与非门各种各样的门电路组合成各种复杂电路。
这里讲一下计算机的发展史:
计算机都是要进行输入输出的:我们将数据喂给它,它处理完后将结果返回。我们编程的本质就在在控制计算机,我们编译代码其实就是在要求计算机帮我们做这做那
早期的计算机都是非常大的,而且其运算力非常差。早期我们没有编程,控制计算机用的是计算机上的开关,早期的计算机科学家都是在计算机前掰来掰去的,其实就是在通过开关来给计算机输入 0 和 1
后来人们觉得开关的方式不太好,到了五六十年代,人们开始用打孔编程。
打孔纸带
打了孔的地方,光能透过去,我们认为是1,否则为0。《三体》中,叶文洁向外星人发送信号时,手上捏着一条纸带,就是这个东西
但打孔编程本质依然是二进制编程,二进制编程可是很恶心的。而且打孔打错了,纸就报废了,要重新打孔,浪费纸张不说还效率低下。后来人们发明了一种编程语言:汇编语言
用汇编语言控制计算机效率无疑比直接二进制编程高很多。
从我们的汇编语言开始,就需要一个东西:编译器
。因为汇编语言本质上也是文本,所以我们需要一种编译器将汇编语言编译成对应的二进制。
这里有个问题:第一个汇编语言编译器是用什么写的呢?
这个编译器要编译汇编语言,那编译器自己应该用什么语言来写呢?
用汇编吗?你用还没法翻译成二进制的汇编,来将汇编翻译成二进制,这不鸡蛋和鸡吗?
因此第一版编译汇编的编译器,是用二进制写的。先用二进制写一个二进制版的汇编编译器。有了第一个编译器,此时就可以编译汇编语言了,此时我们就可以用汇编语言写一份汇编版本的编译器,第一版的编译器就可以不要了,此后我们就可以用自己语言写的编译器编译自己语言。这个过程叫做编译器的自举过程!
不仅如此,语言也是可以自举的。比如C++推出C++11,但此时的编译器只支持C++98,这时就可用98写个能编11的编译器,再用C++11进行重写
最早期的,比较好的操作系统叫 Unix,它第一版本就是由肯·汤普逊用汇编语言写出来的,后来丹尼斯里奇发明了 C语言,肯·汤普逊和丹尼斯里奇即一起用C语言把 Unix 进行重构,发布的 C语言 版本的 Unix。我什么肯·汤普逊最开始用汇编语言写,因为最开始只有汇编,后来 C语言 出来了,C语言 对应的编译器也诞生了,为了代码本身的可维护性,他就把 Unix 操作系统调整为 C语言 了。
再后来,人们觉得汇编语言也太麻烦,所以基于汇编语言产生了许多分支,编译型语言在那个阶段就开始爆发了。最典型的就是 70 年代产生的 C语言,再到后来的 C++/java/go
现在有了 C语言,C语言 最终肯定也要翻译成二进制。现在的问题是,我们是直接将C语言翻译成二进制还是先翻译成汇编语言再翻译成二进制。
我们肯定会选择方案二。为什么呢?
首先将C语言翻译成汇编语言,毕竟还是从文本到文本,它的翻译难度相对较低;其次,在C语言产生之前,汇编语言已经发展了很多年了,我们只需要将C翻译成汇编,而将汇编翻译成二进制这项工作已经发展的很成熟,可以不用做了,我们可以站在巨人的肩膀上。
如果直接将 C 翻译成二进制,那么翻译的成本会特别高,而且 C++ 等后来者是基于C语言发明出来的,你让我 C++ 怎么办,难道我 C++ 也要直接翻译成二进制吗?
我们要学会站在巨人的肩膀上,计算机每一阶段的发展都经过了十几年,我们要将每一阶段的发展好好用上。
而编译是逆历史的过程:C语言 -> 汇编 -> 二进制
好啦,本期关于编译器 gcc/g++ 就介绍到这里啦,希望本期博客能对你有所帮助。同时,如果有错误的地方请多多指正,让我们在 Linux 的学习路上一起进步!
相关文章:
【Linux系统】—— 编译器 gcc/g++ 的使用
【Linux系统】—— 编译器 gcc/g 的使用 1 用 gcc 直接编译2 翻译环境2.1 预处理(进行宏替换)2.2 编译(生成汇编)2.3 汇编(生成机器可识别代码)2.4 链接2.5 记忆小技巧2.6 编译方式2.7 几个问题2.7.1 如何理…...
读西瓜书的数学准备
1,高等数学:会求偏导数就行 2,线性代数:会矩阵运算就行 参考:线性代数--矩阵基本计算(加减乘法)_矩阵运算-CSDN博客 3,概率论与数理统计:知道啥是随机变量就行...
【数据结构篇】顺序表 超详细
目录 一.顺序表的定义 1.顺序表的概念及结构 1.1线性表 2.顺序表的分类 2.1静态顺序表 2.2动态顺序表 二.动态顺序表的实现 1.准备工作和注意事项 2.顺序表的基本接口: 2.0 创建一个顺序表 2.1 顺序表的初始化 2.2 顺序表的销毁 2.3 顺序表的打印 3.顺序…...
Flink把kafa数据写入Doris的N种方法及对比。
用Flink+Doris来开发实时数仓,首要解决是如何接入kafka实时流,下面是参考Doris官方文档和代码,在自己项目开发的实践中总结,包括一些容易踩坑的细节。 目录 Routine Load方法 接入kafka实时数据 踩坑的问题细节 Flink Doris Connector方法 完整示例 Routine Load方法…...
leetcode刷题记录(七十八)——105. 从前序与中序遍历序列构造二叉树
(一)问题描述 105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode)105. 从前序与中序遍历序列构造二叉树 - 给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一…...
imread和jpeg_read在MATLAB中处理图像时的不同
目录 1.功能差异 2.输出格式 3.颜色空间 4.处理阶段 5.用途 6.性能 1.功能差异 imread:这个函数用于读取各种格式的图像文件(包括JPEG、PNG、BMP等)并将其转换为MATLAB中的矩阵。它适用于读取图像并直接在空间域中进行处理。jpeg_read…...
P9069 [Ynoi Easy Round 2022] 堕天作战 TEST_98 Solution
Description 给定长为 n n n 的序列 a ( a 1 , a 2 , ⋯ , a n ) a(a_1,a_2,\cdots,a_n) a(a1,a2,⋯,an),有 m m m 个操作,分以下两种: modify ( l , r , k ) \operatorname{modify}(l,r,k) modify(l,r,k):对于所有…...
SCPI命令笔记
1. 读取设备信息 *IDN? 2. 复位仪器 *RST 3. 清除设备的状态寄存器和事件队列 *CLS 4. 读取设备数据(发一个指令,读取一次) READ? 5. 读取设备电压(功能和第4条命令达到一样的效果) MEAS:VOLT? 6. 读取设备电流 (功能和第4条命令达到一样的效果) MEAS:CURR? 7.…...
TCP创建通信前的三次握手(为啥不是两次?)
1.三次握手的过程 客户端发送 SYN(同步)报文 客户端向服务器发送 SYN 标志的数据包,请求建立连接,表示 "你好,我要连接你"。 服务器回复 SYNACK(同步确认)报文 服务器收到 SYN 后&am…...
2024.ailx10的年终总结
已经工作7年啦,今年网络安全行业愈发寒冷,几乎所有友商都在做安全GPT,说实话,AI确实颠覆了传统的网络安全运营,以前需要安服处置告警,以后可能就不需要了,大家日子都不好过,越是简单…...
洛谷P8837
[传智杯 #3 决赛] 商店 - 洛谷 代码区: #include<stdio.h> #include<stdlib.h> int cmp(const void*a,const void *b){return *(int*)b-*(int*)a; } int main(){int n,m;scanf("%d%d",&n,&m);int w[n];int c[m];for(int i0;i<n;…...
【Day23 LeetCode】贪心算法题
一、贪心算法 贪心没有套路,只有碰运气(bushi),举反例看看是否可行,(运气好)刚好贪心策略的局部最优就是全局最优。 1、分发饼干 455 思路:按照孩子的胃口从小到大的顺序依次满足…...
以太网详解(五)GMII、RGMII、SGMII 接口时序约束(Quartus 平台)
文章目录 接口时序Avalon Streaming 接口时序Receive TimingTransmit Timing GMII 接口时序Receive TimingTransmit Timing RGMII 接口时序Receive TimingTransmit Timing 如何创建 .sdc 约束文件三速以太网系统时钟信号创建 set_input_delay,set_output_delay 约束…...
Java中的错误与异常详解
Java中的错误与异常详解 Java提供了一种机制来捕获和处理程序中的异常和错误。异常和错误都继承自 Throwable 类,但它们有着不同的用途和处理方式。 1. Error(错误) Error 是程序无法处理的严重问题,通常由 JVM(Java…...
使用 HTML 开发 Portal 页全解析
前言 在当今数字化时代,网站作为企业和个人展示信息、提供服务的重要窗口,其重要性不言而喻。而 Portal 页,作为网站的核心页面之一,承担着引导用户、整合信息等关键任务。那么,如何使用 HTML 开发一个功能齐全、界面…...
高并发内存池_CentralCache(中心缓存)和PageCache(页缓存)申请内存的设计
三、CentralCache(中心缓存)_内存设计 (一)Span的创建 // 页编号类型,32位下是4byte类型,64位下是8byte类型 // #ifdef _WIN64 typedef unsigned long long PageID; #else _WIN32 typedef size_t PageI…...
Js:DOM中的样式(包含行内样式、滚动样式、可见区域样式等)
这部分还在更新 1、 获取行内样式:元素.style.样式名称 2、 获取当前正在显示的样式(只能读,不能修改,想要修改要使用style): ① 只有ie支持:元素.currentStyle.样式名称 ② 其他浏览器&…...
【leetcode 26】28.找出字符串中第一个匹配项的下标 | 实现 strStr()==❗不会❗==
在一个串中查找是否出现过另一个串,这是KMP的看家本领。 // 方法一 class Solution {public void getNext(int[] next, String s){int j -1;next[0] j;for (int i 1; i < s.length(); i){while(j > 0 && s.charAt(i) ! s.charAt(j1)){jnext[j];}if…...
Unity自学之旅04
Unity自学之旅04 Unity自学之旅④📝 跳跃🐯 攻击🦄 GUIGUI前置,显示收集物品数量和角色HpUGUI游戏暂停和重新开始 🤗 总结归纳 Unity自学之旅④ 📝 跳跃 public class PlayerBehaviorRigid : MonoBehavio…...
Unreal Engine 5 C++ Advanced Action RPG 十章笔记
第十章 Survival Game Mode 2-Game Mode Test Map 设置游戏规则进行游戏玩法 生成敌人玩家是否死亡敌人死亡是否需要刷出更多 肯定:难度增加否定:玩家胜利 流程 新的游戏模式类游戏状态新的数据表来指定总共有多少波敌人生成逻辑UI告诉当前玩家的敌人波数 3-Survival Game M…...
[Unity 热更方案] 使用Addressable进行打包管理, 使用AssetBundle进行包的加载管理.70%跟练
在正常的开发过程中我们经常遇到一些关于热更的方案,有一些已有的方案供我们选择,但是实机情况往往不尽如人意,各有优缺点. 现在我们同样有一个热更的需求,但是要求打包简单,加载过程可查,防止出现一些资源和流程的问题. 下面介绍我在项目中使用的方案. 打包方面使用Addressabl…...
人工智能领域单词:英文解释
目录 1、前言2、单词组1:15个3、单词组2:15个4、单词组3:15个5、单词组4:15个6、单词组5:15个 1、前言 亲爱的家人们,创作很不容易,若对您有帮助的话,请点赞收藏加关注哦࿰…...
工业网口相机:如何通过调整网口参数设置,优化图像传输和网络性能,达到最大帧率
项目场景 工业相机是常用与工业视觉领域的常用专业视觉核心部件,拥有多种属性,是机器视觉系统中的核心部件,具有不可替代的重要功能。 工业相机已经被广泛应用于工业生产线在线检测、智能交通,机器视觉,科研,军事科学,航天航空等众多领域 …...
NextJs - ServerAction获取文件并处理Excel
NextJs - ServerAction获取文件并处理Excel 一. 客户端二. ServerAction 处理 一. 客户端 use client; import { uploadExcel } from actions/batchInquirySystem/api; import type { UploadProps } from antd; import { Upload } from antd;/*** 创建问询内容*/ const Page …...
【深度学习项目】语义分割-FCN网络(原理、网络架构、基于Pytorch实现FCN网络)
文章目录 介绍深度学习语义分割的关键特点主要架构和技术数据集和评价指标总结 FCN网络FCN 的特点FCN 的工作原理FCN 的变体和发展FCN 的网络结构FCN 的实现(基于Pytorch)1. 环境配置2. 文件结构3. 预训练权重下载地址4. 数据集,本例程使用的…...
集群、分布式及微服务间的区别与联系
目录 单体架构介绍集群和分布式架构集群和分布式集群和分布式区别和联系 微服务架构的引入微服务带来的挑战 总结 单体架构介绍 早期很多创业公司或者传统企业会把业务的所有功能实现都打包在一个项目中,这种方式就称为单体架构 以我们都很熟悉的电商系统为例&…...
ConvBERT:通过基于跨度的动态卷积改进BERT
摘要 像BERT及其变体这样的预训练语言模型最近在各种自然语言理解任务中取得了令人印象深刻的性能。然而,BERT严重依赖于全局自注意力机制,因此存在较大的内存占用和计算成本。尽管所有的注意力头都从全局角度查询整个输入序列以生成注意力图࿰…...
C# 网络协议第三方库Protobuf的使用
为什么要使用二进制数据 通常我们写一个简单的网络通讯软件可能使用的最多的是字符串类型,比较简单,例如发送格式为(head)19|Msg:Heart|100,x,y,z…,在接收端会解析收到的socket数据。 这样通常是完全可行的,但是随着数据量变大&…...
「2024 博客之星」自研Java框架 Sunrays-Framework 使用教程
文章目录 0.序言我的成长历程遇到挫折,陷入低谷重拾信心,迎接未来开源与分享我为何如此看重这次评选最后的心声 1.概述1.主要功能2.相关链接 2.系统要求构建工具框架和语言数据库与缓存消息队列与对象存储 3.快速入门0.配置Maven中央仓库1.打开settings.…...
【Elasticsearch】Springboot编写Elasticsearch的RestAPI
RestAPI 初始化RestClient创建索引库Mapping映射 判断索引库是否存在删除索引库总结 ES官方提供了各种不同语言的客户端,用来操作ES。这些客户端的本质就是组装DSL语句,通过http请求发送给ES。 官方文档地址 由于ES目前最新版本是8.8,提供了全…...
Swift语言的学习路线
Swift语言的学习路线 引言 在现代程序开发中,Swift语言逐渐成为了移动应用程序开发的重要工具,尤其是在iOS和macOS平台上。自2014年发布以来,Swift以其易读性和强大的功能,受到越来越多开发者的青睐。对于初学者而言,…...
63,【3】buuctf web Upload-Labs-Linux 1
进入靶场 点击pass1 查看提示 既然是上传文件,先构造一句话木马,便于用蚁剑连接 <?php eval($_POST[123])?> 将这两处的检查函数删掉 再上传木马 文件后缀写为.php 右键复制图片地址 打开蚁剑连接 先点击测试连接,显示成功后&…...
Leetcode:2239
1,题目 2,思路 循环遍历满足条件就记录,最后返回结果值 3,代码 public class Leetcode2239 {public static void main(String[] args) {System.out.println(new Solution2239().findClosestNumber(new int[]{-4, -2, 1, 4, 8})…...
自然语言处理与NLTK环境配置
自然语言处理(Natural Language Processing, NLP)是人工智能的重要分支,专注于计算机如何理解、分析和生成自然语言。自然语言是人类用于交流的语言,如中文、英文等,这使得自然语言处理成为沟通人与计算机的桥梁。近年来,NLP在诸多领域得到广泛应用,包括文本分析、语言翻…...
分布式搜索引擎02
1. DSL查询文档 elasticsearch的查询依然是基于JSON风格的DSL来实现的。 1.1. DSL查询分类 Elasticsearch提供了基于JSON的DSL(Domain Specific Language)来定义查询。常见的查询类型包括: 查询所有:查询出所有数据,…...
使用 Logback 的最佳实践:`logback.xml` 与 `logback-spring.xml` 的区别与用法
在开发 Spring Boot 项目时,日志是调试和监控的重要工具。Spring Boot 默认支持 Logback 作为日志系统,并提供了 logback.xml 和 logback-spring.xml 两种配置方式。这篇文章将详细介绍这两者的区别、各自的优缺点以及最佳实践。 目录 一、什么是 Logbac…...
【爬虫开发】爬虫开发从0到1全知识教程第12篇:scrapy爬虫框架,介绍【附代码文档】
本教程的知识点为:爬虫概要 爬虫基础 爬虫概述 知识点: 1. 爬虫的概念 requests模块 requests模块 知识点: 1. requests模块介绍 1.1 requests模块的作用: 数据提取概要 数据提取概述 知识点 1. 响应内容的分类 知识点:…...
鸿蒙UI(ArkUI-方舟UI框架)-开发布局
文章目录 开发布局1、布局概述1)布局结构2)布局元素组成3)如何选择布局4)布局位置5)对子元素的约束 2、构建布局1)线性布局 (Row/Column)概述布局子元素在排列方向上的间距布局子元素在交叉轴上的对齐方式(…...
代码随想录_字符串
字符串 344.反转字符串 344. 反转字符串 编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。 不要给另外的数组分配额外的空间,你必须**原地修改输入数组**、使用 O(1) 的额外空间解决这一问题。 思路: 双指针 代…...
2025年1月17日(点亮三色LED)
系统信息: Raspberry Pi Zero 2W 系统版本: 2024-10-22-raspios-bullseye-armhf Python 版本:Python 3.9.2 已安装 pip3 支持拍摄 1080p 30 (1092*1080), 720p 60 (1280*720), 60/90 (640*480) 已安装 vim 已安装 git 学习目标:…...
Spring Boot自动配置原理:如何实现零配置启动
引言 在现代软件开发中,Spring 框架已经成为 Java 开发领域不可或缺的一部分。而 Spring Boot 的出现,更是为 Spring 应用的开发带来了革命性的变化。Spring Boot 的核心优势之一就是它的“自动配置”能力,它极大地简化了 Spring 应用的配置…...
React技术栈搭配(全栈)(MERN栈、PERN栈)
文章目录 1. MERN 栈2. PERN 栈3. React Next.js Node.js4. JAMstack (JavaScript, APIs, Markup)5. React GraphQL Node.js6. React Native Node.js结论 React作为前端框架已经成为了现代web开发的重要组成部分。在全栈开发中,React通常…...
Linux - 线程池
线程池 什么是池? 池化技术的核心就是"提前准备并重复利用资源". 减少资源创建和销毁的成本. 那么线程池就是提前准备好一些线程, 当有任务来临时, 就可以直接交给这些线程运行, 当线程完成这些任务后, 并不会被销毁, 而是继续等待任务. 那么这些线程在程序运行过程…...
以Python构建ONE FACE管理界面:从基础至进阶的实战探索
一、引言 1.1 研究背景与意义 在人工智能技术蓬勃发展的当下,面部识别技术凭借其独特优势,于安防、金融、智能终端等众多领域广泛应用。在安防领域,可助力监控系统精准识别潜在威胁人员,提升公共安全保障水平;金融行业中,实现刷脸支付、远程开户等便捷服务,优化用户体…...
使用Sum计算Loss和解决梯度累积(Gradient Accumulation)的Bug
使用Sum计算Loss和解决梯度累积的Bug 学习 https://unsloth.ai/blog/gradient:Bugs in LLM Training - Gradient Accumulation Fix 这篇文章的记录。 在深度学习训练过程中,尤其是在大批量(large batch)训练中,如何高…...
mfc操作json示例
首先下载cJSON,加入项目; 构建工程,如果出现, fatal error C1010: unexpected end of file while looking for precompiled head 在cJSON.c文件的头部加入#include "stdafx.h"; 看情况,可能是加到.h或者是.cpp文件的头部,它如果有包含头文件, #include &…...
C语言练习(18)
一个班10个学生的成绩,存放在一个一维数组中,要求找出其中成绩最高的学生成绩和该生的序号。 #include <stdio.h>#define STUDENT_NUM 10 // 定义学生数量int main() {int scores[STUDENT_NUM]; // 定义存储学生成绩的一维数组int i;// 输入10个…...
LeetCode 热题 100_全排列(55_46_中等_C++)(递归(回溯))
LeetCode 热题 100_两数之和(55_46) 题目描述:输入输出样例:题解:解题思路:思路一(递归(回溯)): 代码实现代码实现(思路一(…...
编译chromium笔记
编译环境: windows10 powershell7.2.24 git 2.47.1 https://storage.googleapis.com/chrome-infra/depot_tools.zip 配置git git config --global user.name "John Doe" git config --global user.email "jdoegmail.com" git config --global …...
PHP语言的数据库编程
PHP语言的数据库编程 引言 随着互联网的发展,动态网站已成为主流,而动态网站的核心就是与数据库进行交互。PHP(超文本预处理器)是一种流行的开源服务器端脚本语言,被广泛用于Web开发。它以其简单易学和功能强大而受到…...