【Linux】makefile项目管理
前言
makefile是一种自动化构建工具,广泛用于管理和编译项目,特别是在C和C++等语言中。它通过定义规则来控制源代码的编译、链接和清理等过程。以下是一个基本的Makefile结构和示例,帮助你理解如何管理项目:
首先:创建的文件名通常只能是:makefile或者Makefile,否则使用make时,将无法直接识别。虽然可以使用-f选项指定makefile文件,(这种一般也会写成lib.mk格式的文件)
基本结构
一个简单的Makefile通常包括以下几个部分:
变量定义:可以定义编译器、编译选项和源文件等。
规则:指定如何构建目标。规则的语法格式如下:
目标:依赖条件(前面是一个严格的tab)命令#eg.
main:main.cgcc -c main.c -o main
伪文件:如clean,用于执行特殊任务(例如清理中间文件)。
脚本:变量
makefile与脚本之间有点关系,例如:
makefile定义了项目中各个文件之间的依赖关系和构建规则,用于自动化编译和构建过程。而脚本(如bash脚本)则是一种通过命令行解释器执行的程序,通常用于执行一系列命令以完成特定的任务,比如自动化系统管理、数据处理等。
二者在功能上都可以用于自动化任务,但Makefile更加专注于文件的生成和管理,特别是与代码编译相关的任务。而脚本可以用于更广泛的任务,包括文件处理、网络请求、系统监控等,超出构建的范围。
Makefile通常在Linux系统中使用make工具来执行,他会根据规则和依赖关系自动选择需要执行的命令。脚本则可以在任何支持相应解释器(如bash、python、perl等)的环境中运行。
但不可避免地,这两者可能都需要用到同一个知识:变量!!!
这个词我们并不陌生,只是变量在Linux中充当着什么样的角色呢?通常我们在学习shell编程时可能会接触这个概念,在这里,我们先简单的预习一下。请移步下面正文:
Shell变量
定义变量
在Shell编程中,变量是用于存储数据值的名称。定义变量时,变量名不用加美元符号($,PHP语言需要加,就不提了),如:
your_name="stark"
注意,变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不太一样。同时,变量命名需要遵循以下规则:
1.只含字母、数字、下划线:字母大小写敏感,不能以数字开头,这条和C/C++一样,注意一下即可。
2.避免使用关键字:C/C++也是需要避免关键字的,Shell也一样,需要避免的关键字例如:(if,then,else,fi,for,while)
3.使用大写字母表示常量:Shell的常量就类似于宏了,一般使用全大写字母命名,如PI=3.14等
4.避免特殊符号:像$、@、*等特殊符号不要用在命名当中,因为这些东西在Shell语法中具有特定的功能与含义。包括空格也不要使用,因为空格通常用于分隔参数和命令。
Tips:这些命名规则大多与C/C++一致,唯一需要注意的是等号左右无需空格,而且可以无需指定数据类型。
#有效的命名方式:
var1="123"
var2="stark"#无效的命名方式:
var_$="33" #特殊字符$
?var="111" #特殊字符?
a*b="356" #特殊字符*
c and d="156" #避免空格
使用变量
使用一个定义过的变量,只要在变量名前加上美元符号$(读作:dollar--刀乐儿,也就是所谓的美刀)即可,如:
var1="stark"echo $var1
echo ${var1}
变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界,因为有时候我们在使用时极有可能不能明确边界,举例说明:
skill="write_code"
echo "I am good at ${skill}and others"
假如我们没有花括号指定边界,那么就写成了:
echo "I am good at $skilland others",解释器尝试寻找skilland这个变量,但是这并不是我们期望的。所以良好的编程习惯是给所有的变量加上边界(花括号)。
已经定义的变量可以被重新赋值,这一点也很好理解,只不过此时我们使用变量无需加$,因为严格来说,重新赋值就是重新定义,加上$符后我们会将变量的值来替换掉该内容,就无法进行赋值了。
这里还有一个概念叫做:只读变量。使用readonly命令可以将变量定义成只读变量,只读变量的值不能被修改,相当于C/C++的const,下面给出语法:
c_var_myname="i am stark!"
readonly c_var_myname
在这里,我们使用变量来为其添加修饰时也不需要使用$符,目前看来,只有在打算使用变量的值时才会使用$符。
删除变量
不同于一般的编程语言,Shell脚本语言中,具有删除变量的概念,语法是:
unset var_name
变量被删除后不可再次使用,unset不能删除只读变量。你可以理解为,只读变量只有被读的权限,不可改变其值,亦不可改变其存在状态。
注释与引号
注释:(Shell 变量 | 菜鸟教程)我一般只使用 #单行注释
#单行注释#使用Here文档:
:<<EOF注释内容...
注释内容...语法--冒号+<<+EOF+多行注释内容+EOF
EOFEOF可以替换其他符号
: <<'COMMENT'
注释内容
COMMENT:<<'
注释内容
'
:<<!
注释内容
!#直接使用冒号
: '多行注释1,
语法为--冒号+空格+单引号+多行注释内容+单引号'
引号:
变量定义时,可以加引号也可以不加引号,加的引号可以是单引号也可以是双引号。
#单引号
str1='this is a string'#双引号
str2="this is a string"#无引号
var=hello
1.单引号的限制:
单引号里的任何字符都会原样输出,单引号内变量是无效的
单引号字符串中不能出现单独的一个单引号,对单引号使用转义符也不行
2.双引号的优点:
双引号里可以有变量
双引号里可以出现转义字符
eg:
name="stark"
var="hello,i am \" &{name} \"! \n"
echo -e $var
环境变量
由操作系统或用户设置的特殊变量,用于配置Shell的行为和影响其执行环境。例如,PATH变量包含了操作系统搜索可执行文件的路径:
echo $PATH
特殊变量
有一些特殊变量在Shell中具有特殊含义,例如:$0表示脚本的名称,$1,$2等表示脚本的参数,$#表示传递给脚本的参数数量,$?表示上一个命令的退出状态等。
有了以上的知识,我们在使用makefile的比较“高大上”的用法的时候就不显得茫然无措了(makefile中的变量与上述变量有些差别,但还是不耽误理解的)。
Makefile
sudo apt-get install make #下载make工具
基本原则:
1.若想生成目标,检查规则中的依赖文件是否存在,如不存在,则寻找是否有规则用来生成该依赖文件。
2.检查规则中的目标是否需要更新,必须先检查它的所有依赖,依赖中有任一个被更新,则目标必须更新
⚪分析各个目标和依赖之间的关系
⚪根据依赖关系自底向上执行命令
⚪根据修改时间比目标新,确定更新
⚪如果目标不依赖任何条件,则执行对应命令,以示更新
1个规则:
object:link.cgcc link.c -o object#模板:
目标:依赖文件(tab)命令
示例:
创建一个测试用的.c文件:vim main.c
#include <stdio.h>int main()
{printf("------------");return 0;
}
然后创建一个makefile文件:vim makefile
main:main.cgcc main.c -o main
然后再退出转到终端输入:make
执行完make命令后,下面会提示make自动执行的命令(gcc main.c -o main),然后使用ls命令查看当前目录下的文件,发现多了一个main文件,这就相当于直接执行gcc main.c -o main。你可能觉得又是新建文件,又是按规则编辑内容的,我为什么不直接执行命令呢。诚然,但是假如你需要分使用gcc分步骤制作时呢?每次都一句一句的执行?那么我配置一次makefile,之后就都make就玩事了。(一次制作,受益良久)
main:main.ogcc main.o -o mainmain.o:main.sgcc -c main.s -o main.omain.s:main.igcc -S main.i -o main.smain.i:main.cgcc -E main.c -o main.i
这里一连四条语句,每次都自己输入会很麻烦的,但是现在只需要make一下。但是我们也可以看到:这里make之后的执行顺序:是按照我们gcc分步编译的顺序来的,并不是我们在文件中写的顺序来的,这是为什么?这就是基本原则一:检查规则中的依赖文件是否存在,如不存在,则寻找是否有规则用来生成该依赖文件。书写时,我们的目标是main,依赖文件时main.o,检查一下,依赖文件并不存在,那么就会寻找文件中是否有生成该依赖文件的规则,发现了gcc -c的命令,但是main.o的依赖文件main.s也不存在,所以接着寻找,直到找到main.c,main.c生成main.i后,按照流程最后生成了我们的目标文件main。
下面,在这个基础上,我们修改一下main.c文件,使其打印内容变一下,观察结果
更改之前是输出一行星号:
此时看一下我们的目录下有哪些文件:
下面我们重新执行make指令,那么现在,我们目录中有main.o文件,我们还需要寻找生成依赖文件的规则吗?答案是显然的,需要!!为什么呢,请看规则二:检查规则中的目标是否需要更新,必须先检查它的所有依赖,依赖中有任一个被更新,则目标必须更新。目标存在,那么就检查它的依赖,然后逐层检查依赖,这时依赖链中有更改的,那么久重新执行,更新目标文件。所以此时再执行main时:输出了一行减号。
我们再将main.c改回来:然后删除main、main.i、main.s,保留main.o和main.c。
此时,一开始目标不存在,有main.o这个依赖文件,我们是按照现在的main.o编译输出一行减号,还是重新编译输出一行星号呢?请看VCR:
结果是,更新main.o,因为此时main.o作为一个中间的临时目标,依然会寻找main.o的依赖链,最后导致main.o被更新,从而引起了main的更新。
但是.o .s .i 的文件必须按照依赖链逐层写在makefile文件中吗?根据我们的执行顺序我们发现显然不需要。但是我们试图将生成main目标的规则写在下面呢?
我们执行make,结果提示main.i已经是最新,代表make将main.i当作了最终目标文件,但这并不是我们的预期结果,我们的预期是生成main文件。
我们尝试更改main.c使main.i不是最新:
结果只执行了一句,剩下的三个规则的目标文件并不在main.i的生成的依赖链中,所以不会执行。此时我们得出结论:
第一个规则会被make当作最终的目标文件,只要目标规则为第一条规则,那么其他规则的顺序并不影响最终结果。
但是,我们可以通过在一开始显式声明目标的方式指定最终目标,即在第一有效行添加一句:
ALL:目标文件
好了,现在我们有另外的一个需求:如何在makefile中封装gcc main.c add.c sub.c -o a.out
目前我们学的,只能这么用啊:
main:main.c add.c sub.cgcc main.c add.c sub.c -o main
好了,开始使坏了:我先对add.c进行修改,然后make,然后再执行./main,结果是目标被更新了 。但是,我只修改了add.c,但是执行的却是gcc main.c add.c sub.c -o main,sub.c没修改,也被牵连着被重新编译了一下。明明是add.c不干好事,被老板罚加班了,但是还要连累sub.c也要跟着加班,这公平吗。话说回来,add.c自己变化了,我只需要重新编译它自己就完了嘛。但我们上面的写法就已经决定了,它们三个共同编译才能生成main,不能单独修改一个然后去修改main。所以需要我们重新制定规则:
命令形式:(自己去尝试写成makefile规则形式)
此时,如果更改其中一个文件的话,只会重新编译单独那一个,最后链接再一起执行,我们知道,链接阶段最耗时,所以,此时我们将最耗时的给分离了,只剩下一些细枝末节的链接操作,还是能接受的。还是那个例子,add偷懒连累了sub,但是老板比较好,只让sub给add打个杂,不用做那些最累的活了。
2个函数:
①src = $(wildcard *.c)
wildcard函数:找到当前目录下所有后缀为.c的文件,赋值给src
wildcard:中文释义为通配符。上面的语法是:定义一个变量src,调用$()函数wildcard,传入参数*.c,将调用的函数的 结果(文件名)组成列表 赋给src中做初值。
②obj = $(patsubst %.c,%.o, $(src))
patsubst函数:把src变量里面的所有后缀为.c的文件替换成.o
patsubst:全称是“pattern substitution”,即模式替换。这个函数可以在给定的文本中查找符合特定模式的单词,并将其替换为指定的替换文本。上述语法中:将参数3中含有参数1的文本,替换为参数2的文本。
clean:clean是一组没有依赖文件的规则:
clean:-rm -f $(obj) a.out #rm前的-表示:出错依然执行#终端:
localhost$ make clean -n #模拟执行,会将执行的命令输出到终端,但不执行
localhost$ make clean #执行clean
下面我们说一下rm前面的那个-,现在我们的目录下没有aaa文件,我们试图删除aaa:
但是我们将-加载rm前面的话,将不会提示这个错误。
3个自动变量:
自动变量
自动变量只允许出现在命令位置,目标和依赖位置不可出现
①$@:表示规则中的目标/
②$<:表示规则中的第一个依赖条件/
③$^:表示规则中的所有依赖条件,组成一个列表,以空格隔开,如果这个列表中有重复项,则消除重复项。/
使用自动变量的目的是为了方便后面的拓展
模式规则
至少在规则的目标定义中要包含%,%表示一个或多个,在依赖条件中同样可以使用%,依赖条件中的%的取值,取决于其目标。
%.o:%.cgcc -c $< -o $@
之后,我们新建.c文件后,并不需要我们再去动makefile了。
静态模式规则:
$(obj):%.o:%.cgcc -c $< -o %@
伪目标:
.PHONY: all clean
在这句话里面clean就是伪目标
伪目标可以用来简化常用命令的执行,比如清理、安装或测试,而不依赖于文件的生成。
伪目标避免与目录或文件名冲突。由于伪目标总是被执行,其定义不会受到同名文件的影响,确保执行的顺序和安全性。
使用伪目标可以提高 Makefile 的可读性,帮助开发者更清晰地理解可用的命令和操作。
终极形态
#变量定义
CC = gcc
CFLAGS = -Wall -g
SRC = main.c demo01.c demo02.c
OBJ = $(SRC:.c=.o) #等价于 OBJ = $(patsubst %.c,%.o, $(SRC))
TARGET = my_program#默认规则
all:$(TARGET)$(TARGET): $(OBJ)$(CC) $^ -o $@%.o: %.c$(CC) -c $< -o $@ $(CFLAGS)#清理目标
clean:-rm -f $(OBJ) $(TARGET)#伪目标
.PHONY: all clean
说明:
1.变量定义:
CC:指定使用的编译器
CFLAGS:编译选项,-Wall启用警报,-g生成调试信息
(此外还有预处理选项CPPFLAGS:如-I;链接器选项LDFLAGS:如-L -l)
SRC:源文件列表
OBJ:将源文件列表转换为目标文件列表。
TARGET:最终可执行文件的名称
2.默认规则:
目标all默认用来生成可执行文件。
$(TARGET)需要依赖于对象文件
$(OBJ)通过规则定义如何链接这些对象文件
3.模式规则:
%.o: %.c规则使得每个.c文件都可以自动生成对应的.o文件
4.清理:
clean目标用于删除编译产生的临时文件和最终可执行文件,使用rm -f强制删除
5.伪目标:
.PHONY指令clean和all是伪目标,即使有同名文件也不会影响执行。
使用方法
在项目的目录下打开命令行,运行以下命令:
make #编译项目
make clean #清理项目
通过使用 Makefile,可以简化编译和项目管理的过程,特别是在大型项目中。
但是每次使用make或者make clean,我们都会发现文件里面用到的指令都会被输出到终端,为了将封装性更加彻底,我们可以选择在指令的前面加上@来对其进行匿名执行:
我们gcc这行已经是在匿名执行了,所以gcc命令本身没有输出到终端,而echo命令没有使用匿名方式@,所以命令本身以及命令结果都输出到了终端。
感谢大家!!!最后附上C语言常用的makefile文件内容:
#编译变量---------------------------------------------------------------------------------
CC = gcc #指定编译器
#CPPFLAGS = -l #预处理选项
CFLAGS = -Wall -g #编译器选项
LDFLAGS = -l math -L /home/stark/class/filec/library/lib #链接器选项
#不使用动态库的话,这块也不用加#文件变量---------------------------------------------------------------------------------TARGET = a.out #设置终极目标
SRC = $(wildcard *.c) #所有的.c文件为源文件
OBJ = $(patsubst %.c,%.o, $(SRC)) #替换文本.c -> .o
#OBJ = $(SRC:.c=.o)#定义规则---------------------------------------------------------------------------------
ALL:$(TARGET) #指定终极目标$(TARGET):$(OBJ) #终极目标形成规则$(CC) $< -o $@ $(LDFLAGS)%.o:%.c #依赖--OBJ 的生成规则$(CC) -c $^ -o $@ $(CFLAGS)#----------------------------------------------------------------------------------------
#伪目标
.PHONY: all clean
clean:rm -f $(OBJ) $(TARGET)
相关文章:

【Linux】makefile项目管理
前言 makefile是一种自动化构建工具,广泛用于管理和编译项目,特别是在C和C等语言中。它通过定义规则来控制源代码的编译、链接和清理等过程。以下是一个基本的Makefile结构和示例,帮助你理解如何管理项目: 首先:创建…...

Lumos学习王佩丰Excel第二十一讲:经典Excel动态图表实现原理
一、动态图表实现原理 1、理解图表中的数据系列 在Excel图表中,系列指的是图表中的数据集合,它通常代表着一个数据源。每个系列都可以包含多个数据点,这些数据点在图表中以特定的形式展现,如柱状图中的柱子,折线图中…...

Linux框架(二)——pinctrl和gpio子系统
基于设备树的 LED 驱动,但是驱动的本质还是没变,都是配置 LED 灯所使用的 GPIO 寄存器,驱动开发方式和裸机基本没啥区别。 Linux 内核提供了 pinctrl 和 gpio 子系统用于GPIO 驱动,本章我们就来学习一下如何借助 pinctrl 和 gpio…...
C++ string的基本概念
文章目录 1. 什么是string?2. auto和范围for的使用2. 1 auto2. 2 范围for 3. 迭代器的概念、const string的概念3. 1 迭代器的概念3. 2 const string的概念 1. 什么是string? 在了解什么是string之前,我们首先需要知道字符串是什么。在C语言中…...

MAC虚拟机上安装WDA环境
MAC虚拟机上安装WDA环境 一、MAC虚拟机切换root权限二、macOS上安装xcode若你的macOS系统可以在appstore下载安装若你安装的macOS系统版本太低,无法在appstore上安装xcode 三、macOS上安装WebDriverAgent四、使用xcode配置WDA安装到手机上高版本系统支持 一、MAC虚拟…...

与 Cursor AI 对话编程:2小时开发报修维修微信小程序
本文记录了如何通过与 Cursor AI 对话,全程不写一行代码的情况下,完成一个完整的报修小程序。整个过程展示了 AI 如何帮助我们: 生成代码 、解决问题、优化实现、完善细节。 先看一下效果图: 一、项目配置 首先我是这样和 AI 对…...

leetcode-73.矩阵置零-day5
class Solution {public void setZeroes(int[][] mat) {int m mat.length, n mat[0].length;// 1. 扫描「首行」和「首列」记录「首行」和「首列」是否该被置零boolean r0 false, c0 false;for (int i 0; i < m; i) {if (mat[i][0] 0) {r0 true;break;}}for (int j …...

CSS学习记录13
CSS组合器 组合器是解释选择器之间关系的某种机制。CSS选择器可以包含多个简单选择器。在简单选择器之间,我们可以包含一个组合器。 CSS中有四种不同的组合器: 后代组合器(空格)子选择器(>)相邻兄弟选择器&#…...

CAD图纸加密软件哪个最好用 | 安全可靠的解决方案
CAD图纸加密软件哪个最好用 | 安全可靠的解决方案 图纸文件泄密事件频发,给企业带来了严重的商业损失、技术秘密泄露、公共安全威胁以及信誉损害。 为了应对这一挑战,选择一款既安全可靠又易于使用的CAD图纸加密软件显得尤为重要。 在众多加密软件中&a…...

基于SSM+Vue的宠物医院管理系统
作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:…...
处理VUE框架中,ElementUI控件u-table空值排序问题
按照以下步骤进行操作: 分离数据:首先,将原始数据按照username为空和非空进行分类。对非空表进行排序:对非空表按照username进行升序排序。合并表格:将空表和排序后的非空表合并,保证空表挂接在排序后的非…...

专业140+总分400+北京理工大学826信号处理导论考研经验北理工电子信息与通信工程,真题,大纲,参考书。
考研总分400,专业826信号处理导论(信号与系统和dsp)140,成功上岸北理工,虽然已经一段时间,但是后劲很大,每每回想还是昨日事,群里同学多次要求分享自己的一些经验,感谢大…...
Rocky DEM tutorial5_Drop Weight test_落锤试验
tutorial5_Drop Weight test_落锤实验 文章目录 tutorial5_Drop Weight test_落锤实验0. 目的1. 模型介绍2. 模型设置2.1 设置Physics2.2 导入几何2.3 定义进口面2.4 设置motion frames2.5 设置边界条件2.6 设置材料2.7 设置 materials interactions2.8 设置 Particles2.9 设置…...

C#,在 C# 语言中将 LaTeX 转换为 PNG 或 JPG 图像
在 C 语言中将 LaTeX 转换为 PNG 或 JPG 图像# 12月 28, 2021 2 分钟 法尔汉拉扎 在 C 语言中将 TeX 转换为 PNG JPG 图像# TeX 格式用于处理技术和科学文件。它通常用于交流或发布此类文档。在某些情况下,您可能需要将 TeX 文件渲染为 PNG 或 JPG 等图像…...
Elasticsearch:Mapping-映射
一、创建索引 自动生成索引字段数据类型即自动映射 创建之前,先删除索引防止重复创建 删除索引: DELETE product_mapping创建索引 product_mapping并且赋值 PUT /product_mapping/_doc/1 {"name": "xiaomi phone","desc": "s…...
安装Tensorflow@FreeBSD(失败)
pkg 安装,失败,找不到:pkg: No packages available to install matching science/py-tensorflow have been found in the repositories ports安装 cd /usr/ports/science/py-tensorflow make install 报错: 按照提示重新发命令 make DISABLE_VULNERA…...

API接口示例:电商商品评论数据
当然,以下是一个简化的电商商品评论数据API接口的示例。请注意,这只是一个示例,实际的API接口可能会更加复杂,并且会包含更多的验证、错误处理和安全措施。 API接口示例:电商商品评论数据 基础信息 API名称…...

使用idea创建一个JAVA WEB项目
文章目录 1. javaweb项目简介2. 创建2.1 idea新建项目2.2 选择,命名2.3 打开2.4 选择tomcat运行2.5 结果 3. 总结 1. javaweb项目简介 JavaWeb项目是一种基于Java技术的Web应用程序,主要用于开发动态网页和Web服务。这种项目能够构建在Java技术栈之上&a…...
解决MyBatis在 Oracle 中使用 IN 语句不能超过 1000 问题
在 Oracle 数据库中,IN 语句常用于查询某个字段是否属于一组特定的值。对于大多数开发者而言,IN 是一种简单直观的查询方式,能够提升开发效率,避免过多的 OR 语句。然而,许多人在使用 IN 语句时可能遇到一个问题&#…...

最长递增子序列两种算法实现(动态规划,二分查找)
恭喜你刷到博主 DP 经典题目详解部分第一期,想学好 DP 请关注订阅,会持续更新!!!!! 建议先阅读DP算法入门 00001 最长递增子序列(Longest Increasing Subsequence,简写…...
使用 Python + SQLAlchemy 创建知识库数据库(SQLite)—— 构建本地知识库系统的基础《一》
📚 使用 Python SQLAlchemy 创建知识库数据库(SQLite)—— 构建本地知识库系统的基础 🧠 一、前言 随着大模型技术的发展,越来越多的项目需要构建本地知识库系统来支持 RAG(Retrieval-Augmented Generat…...
在C语言中使用UUID作为AES加密密钥
在C语言中使用UUID作为AES加密密钥 编译依赖安装示例代码编译和运行关键点说明注意事项编译依赖安装 运行环境位centos8 Linux 4.18.0-348.7.1.el8_5.x86_64 #1 SMP Wed Dec …...
STM32学习笔记:定时器(TIM)原理与应用(详解篇)
前言 定时器是STM32微控制器中最重要且最常用的外设之一,它不仅能提供精确的定时功能,还能实现PWM输出、输入捕获、编码器接口等多种功能。本文将全面介绍STM32的通用定时器,包括其工作原理、配置方法和典型应用。 一、STM32定时器概述 定…...

408第一季 - 数据结构 - 线性表
只能用C/C! 顺序表 闲聊 线性表的逻辑顺序和物理顺序相同 都是1234 顺序表的优点: 随机访问,随机访问的意思是访问的时间 和位置没有关系,访问下标1和100一样的,更深层就是直接计算 a100 * 数组大小,随便…...
类型别名与类型自动推导
类型别名与类型的自动推导 类型别名 为什么要引入类型别名? 为了给类型赋予特殊含义或便于使用 典型用途 (1)增强代码可移植性 例如:size_t (在不同系统中可能是unsigned int 或 unsigned long) 首先是…...
PostgreSQL 的扩展pageinspect
PostgreSQL 的扩展pageinspect pageinspect 是 PostgreSQL 提供的一个强大的底层扩展,允许数据库管理员和开发者直接检查数据库页面的内部结构。这个扩展对于数据库调试、性能优化和深入学习 PostgreSQL 存储机制非常有价值。 一、扩展概述 功能:提供…...

IDEA中的debug使用技巧
详细教学视频见b站链接:IDEA的debug调试 CSDN详细博客文章链接:debug文章学习 以下为个人学习记录总结: idea中的debug模式界面如下: 现在详细介绍图标作用: 图标一(Show Execution Point)&…...

基于SFC的windows系统损坏修复程序
前言 在平时使用Windows操作系统时会遇到很多因为系统文件损坏而出现的错误 例如:系统应用无法打开 系统窗口(例如开始菜单)无法使用 电脑蓝屏或者卡死 是如果想要修复很多人只能想到重装系统。但其实Windows有一个内置的系统文件检查器可以修复此类错误。 原理 SFC命令…...

Playwright 测试框架 - .NET
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】...

Rust 学习笔记:关于 Cargo 的练习题
Rust 学习笔记:关于 Cargo 的练习题 Rust 学习笔记:关于 Cargo 的练习题问题一问题二问题三问题四问题五问题六问题七 Rust 学习笔记:关于 Cargo 的练习题 参考视频: https://www.bilibili.com/video/BV1xjAaeAEUzhttps://www.b…...