当前位置: 首页 > news >正文

【C语言】深入理解指针

目录

1.字符指针

2.指针数组

3.数组指针

4.数组传参与指针传参

一维数组传参

二维数组传参

一级指针传参

二级指针传参

5.函数指针

6.函数指针数组

7.指向函数指针数组的指针(了解即可)

8.回调函数

回调函数的应用:库函数qsort

模拟实现库函数qsort


1.字符指针

允许用字符串来初始化字符指针

char*p="abcdef"这个语句是正确的,他表示把后面字符串首元素地址放到指针变量p里面去。其中abcdef是一个常量字符串

看下面这个代码

刚上来的两句是创建了两个字符数组,并用hello bit来初始化他们,这两个数组的创建必然要申请两块不同的内存空间,而打印的条件是str1==str2,而数组名是数组首元素地址,所以不满足if的条件,因此会打印str1 and str2 are not same。

然后是用常量字符串初始化字符指针的操作,对于常量字符串hello bit来讲,他存放在内存的代码段,他的地址是固定的,用他的地址来初始化str3和str4,因此str3和str4里面存放的都是常量字符串hello bit的首元素地址,因此打印的是str3 and str4 are same。

2.指针数组

指针数组顾名思义就是用来存放指针的数组,本质上还是一个数组,用来存放一组类型相同的指针。

比如这样一个代码

他们在内存中存放的形式如图

如果拿到了arr[0],也就是arr数组的第一个元素,里面存的是arr1,他指向了arr1数组,也就是说arr[0]就是arr1,arr1[0]表示arr1数组的首元素,又因为arr1就是arr[0]所以arr[0][0]就是arr1的首元素,这看起来像一个二维数组,同理arr[1][0]就是arr2数组的首元素。

虽然形式上跟二维数组一样,但是指针数组跟二维数组还是有很大区别的,二维数组在创建的时候在内存中被分配的空间是连续的,而这个指针数组再创建的时候就是存了三个指针,这个指针指向了三个数组,这三个数组并不一定连续。也就是说对于一个三行五列的二维数组(假设数组名为arr)来说,arr[0][4],arr[1][0]的地址是连续的,但是对于上面的指针数组来说arr[0][4]是arr1的第五个元素,而arr[1][0]是arr2的首元素,由于arr1和arr2在向内存申请空间的时候都是随机申请的,大概率不连续,因此这个指针数组arr的arr[0][4]和arr[1][0]也是大概率不连续的。

3.数组指针

类比一下我们熟悉的其他类型指针,比如int *p,*代表p是一个指针,int代表p指向的数据是int类型的,数组指针也类似,比如int *p[10],*代表p是一个指针,去掉*p之后剩下的int [10]是其指向数据的类型,这是一个数组类型。因此p就叫做数组指针变量,里面存放的是一个数组的地址。p的类型我们写作int(*)[10]。

在对数组指针变量进行初始化的时候,应该写成 int(*p)[10]=&arr;

可以这样理解,首先得有个指针变量p,然后他前面得有个*表示他是一个指针,此时如果没有(),p就会和[]结合,因此我们加上括号,让p和*结合代表他是一个指针。指向的元素是int [10]类型的,存放的内容是arr的地址。同时印证了这个数组指针的类型是int(*)[10],因为去掉指针变量的名字,就是他的类型。

数组指针的使用

先来看一个不合适的使用方法

说我们要打印这个数组的每个元素,这里代码使用了数组指针的方式,首先&arr代表取出整个数组的地址(arr在一般情况下表示数组首元素地址,但是有两个例外,一个是arr单独放在sizeof内部,另一个数&arr,这两种情况下arr代表的是整个数组),既然是一个数组的地址,我们就要放在数组指针里面,因此我们创建了一个int(*)[10]类型的指针变量p,用来存放arr的地址,然后我们要打印arr中的每个元素,肯定要对p进行解引用,*p拿到了arr(可以理解成&和*抵消了),要想打印arr中的每个元素,我们现在知道了arr的首元素地址(因为这里拿到arr是通过解引用,并不属于上面的两种特殊情况,因此这里arr就是数组首元素地址,是int*类型的),想要打印,直接就*(arr+i)即可。也就是说打印的时候应该*((*p)+i),非常的别扭。因为我们想要打印整个数组的内容,直接使用一个int*类型的指针即可,这里却使用了数组指针显然是不合理的,那么数组指针到底应该怎么用?

这里直接给出答案:数组指针在访问二维数组的时候比较方便。

假如有这样一个二维数组arr

当然这只是为了方便理解才画成这样,实际上因为二维数组中每个元素在内存中是连续存放的,他们应该排成一条线。

二维数组可以理解成里面有三个一维数组,也就是说二维数组是一维数组的数组。而二维数组的数组名也代表首元素的地址,首元素又是一个一维数组,因此二维数组的数组名是一个一维数组的地址,我们如果想要把他存起来,应该使用一个数组指针。那么下面这个代码就可以实现二维数组元素的打印

因为arr包含三个一维数组,每个一维数组是四个元素,因此arr的数组名也就是首元素地址是一个int [4]类型的数组的地址,类型是int(*)[4],因此在形参接收的时候应该写int(*p)[4]。

首先p是int(*)[4]类型的数组指针,+1就会跳过一个int [4]类型的数组,p里面存放的是arr首元素的地址,也就是第一个一维数组的地址,因此*p就拿到了第一个数组,相当于拿到了第一个数组的数组名,也就是说*p是int*类型的,+1就会跳过一个int类型。

*p+i用来访问所有行,*((*p+i)+j)就能访问所有元素了,或者说(*p+i)[j]也可以,他们是等效的。

当然也可以直接形参直接使用二维数组来接收

实际上形参写成数组形式只是语法允许,让我们能够直观的知道接收的是一个数组,本质上地址就是要用指针来接收,即使写成第二种写法,编译器在编译的时候也会编译成我们第一种写法,在为形参开辟空间的时候也是为数组指针开辟一块空间。

4.数组传参与指针传参

一维数组传参

下面哪些传参方式是正确的?

先看test函数的传参,实参是arr,也就是一个int类型数组的数组名,表示首元素的地址,应该用一个int*类型的指针来接收,因此形参写成int*arr是对的,又因为C语言语法允许数组传参的时候用数组接收,因此int arr[]和int arr[10]作为形参也是可以的,因为实参传的只是一个地址,形参部分是不会真正去创建一个数组的,但是语法规定可以用数组来作为形参接收一个数组名,我们甚至可以把形参写成int arr[1000],也是对的,编译器都会按照形参是int *类型的来理解。

再来看test2的传参,arr2是一个指针数组,他的数组名是这个指针数组首元素的地址,也就是一个指针的地址,即二级指针,实参传了二级指针,形参要拿一个二级指针变量来接收,因此形参应该是int **类型的,当然语法允许用和实参代表的数组同类型的数组作为形参来接收,但是本质上形参还是一个指针。

因此上面所有传参均正确。

二维数组传参

test函数实参是一个二维数组的数组名,他代表二维数组arr首元素的地址,又因为二维数组arr是由3个一维数组构成的,每个一维数组又有五个int类型的元素,因此arr的首元素是第一个一维数组的地址,存放他应该用一个数组指针,因此实参应该写成int(*arr)[5],表示arr是一个指针,指向的数组类型是int[5]类型的数组,也就是我们所谓的二维数组里面的一维数组,当然数组名作为实参传递,语法上允许用与arr代表的数组类型相同的数组来作为形参接收,这是为了方便理解,但是系统是不会为形参这个数组去开辟内存空间的,编译的时候仍然会按照数组指针的形式开辟空间。

二维数组在创建的时候可以省略行但是不能省略列,因此正确的形参创建形式有int arr[3][5],int arr[][5],int(*arr)[5]。

注:除去数组名单独放在sizeof括号里还有&数组名这两种情况,二维数组的数组名一定是一个数组指针。

一级指针传参

对于指针传参来说,如果实参是一个一级指针,形参就用同类型的指针来接收即可,二级指针同理,这非常的简单,因此对于指针传参,我们来讨论一下如果我们知道了形参是一个一级指针,实参可能传递的是什么。

可以接收

1.char a=0; test2(&a) 一个char类型变量的地址

2.char ch="abc"; test2(ch);一个char[]类型数组的数组名

3.char a=0;char* p=&a; test2(p);一个char*类型的指针变量

二级指针传参

如果形参已经确定是char**p,可能接收的是什么实参?

可以接收

1.char a=0;char *p=&a;test(&p);一个char*类型指针的地址

2.char a=0;char *p=&a;int**pp=&p;test(pp);一个二级指针

3.char* arr[10];test(arr);一个char*[10]类型数组的数组名

注:数组传参,形参可以用数组形式接收,也可以用指针形式接收,但是指针传参,形参指针写成指针形式。

5.函数指针

函数指针顾名思义就是指向函数的指针,里面存放的是一个函数的地址

来看一段代码

居然是一样的,这说明函数名和&函数名代表的意思都是函数的地址

既然函数有地址,我们就可以把他存到指针变量里面去,这个指针变量就是函数指针,在初始化的时候我们写作void (*p)(),也就是函数的返回值类型以及形参类型决定了他的函数指针是什么样的类型。比如有一个函数

int add(int x,int y),用来存放他的函数指针在初始化的时候就写作

int(*p)(int,int),去掉指针的名字,就是他的类型,因此这个函数指针的类型就是int(*)(int,int)

再比如有一个函数void test(charpc,int arr[10]),初始化他的函数指针就写作void (*p)(char*,int [10]),p的类型就是void(*)(char*,int [10]),10可以省略,也可以写成int *

有了函数指针,我们就可以对他进行解引用来调用函数。如果pf里存放了函数add的地址,那么add(3,5)和(*p)(3,5)就是等效的。实际上*都多余了,因为我们函数名和&函数名其实是一回事,我们可以测试一下

因此我们既然把&add赋给了pf,那就相当于把add赋给了pf,也就是说pf就是add,因此我们直接pf(3,5)也是可以正常调用add函数的

来看两个有趣的代码

首先我们看到最后有个小括号,这肯定代表函数调用,然后左边最外层的括号应该就是就是为了分割开,这样我们就从内部的0开始入手,0前面有一个括号,括号里面是一个类型,这表示把0强制类型转换成函数指针的类型,那么0作为函数指针就代表了一个地址,再对他进行解引用就能调用0地址处的函数。之所以最右边调用的小括号里面啥也没有,是因为这个函数不需要任何参数。这个代码应用场景可能就是我们知道了0地址处有一个函数,想要调用他。

这个代码看起来无从下手,因为他好像也并没有函数调用,也没有强制类型转换,如果我提前告诉你,这是一个函数名为signal函数的声明,你有没有头绪了呢?

解释一下,我们就从signal开始入手,因为这肯定是一个函数名,那么他后面的括号就是他的参数类型,分别是int和void(*)(int),也即一个int类型和一个函数指针类型,那么知道了函数名,函数的参数类型,把他们都去掉,不就是他的返回类型吗?故signal的返回类型是void(*)(int),他的返回值也是函数指针类型。因此上面这段代码是signal的声明。

这个代码之所以难以理解,就是因为这个函数指针的类型写起来非常具有迷惑性,如果把这个函数指针类型进行类型重定义成一个简单的类型,这个代码阅读起来就会非常的轻松。那首先来介绍一下typedef的使用方法,如果是把unsigned int类型重命名为uint,就写作typedef unsigned int uint,如果是把int 类型重命名为ptr_t,就写作typedef int ptr_t

但是如果要把函数指针 int(*)(int)重命名为pint,就不能写tepedef int(*)(int) pint,而应该写成typedef int(*pint)(int)

要把函数指针void(*)(int)重命名为pf_t,就写作typedef void(*pf_t)(int),这样就可以把上面的代码简化为pf_t signal(int,pf_t),这样读起来就舒服多了,一眼就看出这是一个函数的声明。

6.函数指针数组

顾名思义就是这个数组中的每个元素都是函数指针类型。

假如我们要写一个计算器,于是我们就写了下面四个函数

我们发现这些函数的参数和返回值都已相同类型的,那我们就可以把这些函数放到一个数组里面去,怎么放函数?只能放他的函数名吧,那我们又说函数名其实是函数的地址,因此我们放的其实是一些函数的地址,也就是函数指针,当然要用一个函数指针数组来存放,那么如何初始化这个数组?类比int arr[4]={0};这表示arr数组里面能放4个int类型的元素

那么我们想要一个能够放四个int(*)(int,int)类型变量的数组,就初始化成int(*)(int,int) arr[4]是不是?这样理解可以,但是语法规定我们要把arr[4]写到*的旁边,也就是说我们应该这样初始化函数指针数组

注:指针变量在创建的时候,指针变量一定是在*的旁边的。

int(*p)(int ,int),*表示p是个指针,去掉*和p就是指针指向的元素类型是

int(int,int),说明指向的元素是函数类型,单独去掉变量名就是p的类型,也就是说p是int(*)(int,int)类型。

int(*arr[4])(int,int),那么对于简单的计算器这个代码的实现,就可以这样写(计算器只针对整数)

7.指向函数指针数组的指针(了解即可)

假如arr是一个函数指针数组,我们现在&arr,放到指针p里面,则p就是指向函数指针数组的指针,他的类型是什么呢?

首先来看函数指针数组的类型应该怎么写。int(*[4])(int,int),是函数指针数组的类型,现在p要指向他,应该写成int(*(*p)[4])(int,int)=&arr,其中p旁边的那个*表示p是一个指针,去掉p,就是p的类型,所以p的类型是int(**arr[4])(int,int),类型去掉p和他旁边的*,就是p指向的元素的类型,因此p指向的元素类型是int(*[4])(int,int),也即一个函数指针类型。

8.回调函数

函数指针有一个非常重要的用途就是实现回调函数。回调函数就是通过函数指针调用的函数。比如前面的计算器,除了使用函数指针数组来实现,还可以使用函数指针来实现。

其中calc函数就通过函数指针回调了加减乘除的函数,此时的add,sub,mul,div就是回调函数,通过函数指针调用谁,谁就是回调函数

回调函数的应用:库函数qsort

qsort的头文件是stdlib.h

他的四个参数分别是要进行排序的数组base的首地址,base数组的元素个数,每个元素的大小,以及一个函数指针,这个函数指针指向了一个函数,这个函数的参数是两个void*类型的指针,返回类型是int,要求这个函数能够比较参数(这个函数的参数是两个指针)指向的两个元素的大小,规定如果elem1指向的元素比elem2指向的元素大,那这个函数就返回一个大于零的数,反之就返回一个小于零的数,如果elem1和elem2指向的元素一样大,就返回0。

void*类型的指针可以接收任何类型的地址,但是不能直接解引用,由于我们不知道未来要比较的两个函数是什么类型的,那就只能写成void*类型,就可以接收任何类型了,在解引用之前强制类型转换即可。

qsort默认是以升序排列的(如果要降序排列,只需要比较大小的函数返回值上用相反的逻辑即可,比如elem1指向的元素如果比elem2大,就返回一个小于零的数),并且可以排列任何类型的数组。来看一个例子

模拟实现库函数qsort

下面我们将使用回调函数模拟实现qsort,由于目前没有学习快速排序,因此使用冒泡排序代替。

模拟实现,我们就把参数设置成和库函数qsort一样,最后一个函数指针指向的是一个能比较两个元素大小的函数,需要使用者自己编写。

我们排序使用的是冒泡排序的思想,就是比较相邻的两个元素,如果前面比后面大,就交换,那现在的问题是当时冒泡排序是针对整形数组的,比较就是直接base[j]和base[j+1]进行比较即可,但是现在我们想要这个my_sort类型能够对任意类型的数据进行排序,就不能简单的写成base[j]和base[j+1],因为我们连base的类型都不知道,当然也不知道+1会跳过几个字节,也就不知道+1是不是拿到了和base[j]相邻的元素。那么我们干脆一个字节一个字节的操作,因为不管什么类型,大小至少也是一个字节,那如何操作一个字节?很简单,使用char类型的指针即可。因此不管base代表什么类型的数组,我们都先把base强制类型转换成char*类型,那么base[j]其实就是(char*)base+j*size,与他相邻的元素就是(char*)base+(j+1)*size。

这样我们就拿到了要比较的两个元素,但是这两个元素如何比较?直接使用大于号显然是不合理的,这时候就用到了我们的第四个参数,cmp函数,我们需要自己写一个能够比较两个元素大小的函数,并且规定如果前者大,就返回一个大于0的数,反之就返回一个小于0的数,如果二者相等,就返回0。

通过判断cmp函数的返回值,我们就知道了需不需要交换这两个元素。那问题又来了,如何交换?直接创建临时变量吗?那临时变量是什么类型的呢?但是要交换的数据是什么类型,他们最小也有一个字节,那么我们直接一个字节一个字节的交换就行,什么时候才算交换结束呢?当然是交换完size个字节后,就结束了。如图是swap函数的交换

这样我们的my_sort函数就可以正常使用了,比如我们要排序的是一个整形数组,我们就要去写一个能够比较两个整形数据的函数,比如这样写

如果我们要比较两个结构体类型的数据呢?

假如结构体类型是这样的

如何比较两个struct stu类型变量的大小?

由于上面的结构体类型含有两个成员变量,那么要比较struct sut类型变量的大小,就可以按照name的大小来进行比较,也可以按照age的大小进行比较,当然如果按照name的大小来进行比较,就不能直接相减了,因为字符串的比较是用库函数strcmp,这个库函数的返回值逻辑与我们的cmp函数一致,也是前者大就返回大于零的数,后者大就返回小于零的数,一样大就返回0,因此我们如果按照name的大小来比较的话,直接返回strcmp的值就可以,如图

注:由于空指针是无法进行解引用操作的,因此我们在写cmp函数的时候都需要进行强制类型转换,要比较的是什么类型的,就强制类型转换成对应的指针。

相关文章:

【C语言】深入理解指针

目录 1.字符指针 2.指针数组 3.数组指针 4.数组传参与指针传参 一维数组传参 二维数组传参 一级指针传参 二级指针传参 5.函数指针 6.函数指针数组 7.指向函数指针数组的指针(了解即可) 8.回调函数 回调函数的应用:库函数qsort …...

Excel——有效性、二级菜单联动

一、录入规范数据 1.手动输入序列录入有效性信息 选择需要录入有效性的所有单元格 选择【数据】——【有效性】——【有效性】 在【允许】输入的值之间选择【序列】 在【序列】输入框中输入想要选择的值,中间用逗号(必须是英文逗号)隔开 。…...

计算机网络总结

1. 网络分层 网络上进行协议分层的好处 ①分层之后层次之间的耦合程度比较低,上层协议不必了解下层的细节,下层也不必了解上层的细节; ②方便的对某一层的协议进行替换; 真实网络的协议分层 OSI 七层网络模型(教科书&…...

初识文件包含漏洞

目录 什么是文件包含漏洞? 文件包含的环境要求 常见的文件包含函数 PHP伪协议 file://协议 php://协议 php://filter php://input zip://、bzip2://、zlib://协议 zip:// bzip2:// zlib:// data://协议 文件包含漏洞演示 案例1:php://inp…...

AR特效自研AI算法技术解决方案

在当今这个高速发展的数字化时代,增强现实(AR)技术已经成为企业创新和市场竞争的重要手段。美摄科技凭借对AI技术的深厚积累,为企业提供了一套创新的AR特效自研AI算法技术解决方案,旨在满足企业在AR领域的多元化需求。…...

牛客2024年除夕娱乐赛(题解)

比赛地址 : 牛客竞赛_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ A 看题面然后猜!!! #include<bits/stdc.h> using namespace std; int main(){cout << "原神启动" << endl; } B 也是看题面然后猜 : #include<bits/stdc.…...

5 scala的函数式编程简介

与Java一样&#xff0c;Scala 也是使用 Lambda 表达式实现函数式变成的。 1 遍历 除了使用 for 可以对数组、List、Set 进行遍历外&#xff0c;也可以使用 foreach 函数式编程进行遍历&#xff0c;使代码更为简洁。 foreach 的方法签名为&#xff1a; foreach(f: (A) > …...

陪护系统|陪护小程序提升长者护理服务质量的关键

在如今逐渐老龄化的社会中&#xff0c;老年人对更好的护理服务需求不断增加。科技的进步使得陪护小程序系统源码成为提供优质服务的重要途径之一。本文将从运营角度探讨如何优化陪护小程序系统源码&#xff0c;提升长者护理服务的质量。 首先&#xff0c;我们需要对软件的设计和…...

C++算法之双指针、BFS和图论

一、双指针 1.AcWing 1238.日志统计 分析思路 前一区间和后一区间有大部分是存在重复的 我们要做的就是利用这部分 来缩短我们查询的时间 并且在使用双指针时要注意对所有的博客记录按时间从小到大先排好顺序 因为在有序的区间内才能使用双指针记录两个区间相差 相当于把一个…...

【大厂AI课学习笔记】1.5 AI技术领域(3)自然语言处理

今天来梳理自然语言处理的相关内容。 自然语言处理&#xff1a;定义、关键技术、技术发展、应用场景与商业化成功 一、自然语言处理的定义 自然语言处理&#xff08;NLP&#xff09;是人工智能&#xff08;AI&#xff09;领域的一个重要分支&#xff0c;它研究的是如何让计算…...

【数字电子技术课程设计】多功能数字电子钟的设计

目录 摘要 1 设计任务要求 2 设计方案及论证 2.1 任务分析 2.1.1 晶体振荡器电路 2.1.2 分频器电路 2.1.3 时间计数器电路 2.1.4 译码驱动电路 2.1.5 校时电路 2.1.6 整点报时/闹钟电路 2.2 方案比较 2.3 系统结构设计 2.4 具体电路设计 3 电路仿真测试及结…...

【新书推荐】7.3 for语句

本节必须掌握的知识点&#xff1a; 示例二十四 代码分析 汇编解析 for循环嵌套语句 示例二十五 7.3.1 示例二十四 ■for语句语法形式&#xff1a; for(表达式1;表达式2;表达式3) { 语句块; } ●语法解析&#xff1a; 第一步&#xff1a;执行表达式1&#xff0c;表达式1…...

爬山算法优化遗传算法优化极限学习机的多分类预测,p-ga-elm多分类预测

目录 背影 极限学习机 爬山算法优化遗传算法优化极限学习机的多分类预测,p-ga-elm多分类预测 主要参数 MATLAB代码 效果图 结果分析 展望 完整代码下载链接:爬山算法优化遗传算法优化极限学习机的多分类预测,p-ga-elm多分类预测(代码完整,数据)资源-CSDN文库 https://d…...

挑战杯 opencv 图像识别 指纹识别 - python

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于机器视觉的指纹识别系统 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;3分工作量&#xff1a;3分创新点&#xff1a;4分 该项目较为新颖&#xff0c;适…...

【Docker】了解Docker Desktop桌面应用程序,TA是如何管理和运行Docker容器(2)

欢迎来到《小5讲堂》&#xff0c;大家好&#xff0c;我是全栈小5。 这是《Docker容器》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解&#xff0c; 特别是针对知识点的概念进行叙说&#xff0c;大部分文章将会对这些概念进行实际例子验证&#xff0c;以此达到加深对…...

PHP、Python、Java 和 Go语言对比

PHP、Python、Java 和 Go 都是流行的编程语言&#xff0c;每种语言都有其独特的优势和适用场景。下面是对这些语言的一些基本对比&#xff1a; 一&#xff1a;PHP 适用场景&#xff1a;主要用于Web开发&#xff0c;特别是服务器端脚本。 特点&#xff1a;语法简单易懂&#…...

算法题目题单+题解——图论

简介 本文为自己做的一部分图论题目&#xff0c;作为题单列出&#xff0c;持续更新。 题单由题目链接和题解两部分组成&#xff0c;题解部分提供简洁题意&#xff0c;代码仓库&#xff1a;Kaiser-Yang/OJProblems。 对于同一个一级标题下的题目&#xff0c;题目难度尽可能做…...

车载测试中:如何处理 bug

一&#xff1a;Jira 提交 bug 包含那些内容 二&#xff1a;如何处理现上 bug 三&#xff1a;车载相关的 bug 如何定位 四&#xff1a;遇到 bug &#xff0c;复现不出来怎么办 五&#xff1a;bug 的处理流程 一&#xff1a;Jira 提交 bug 包含那些内容二&#xff1a;如何处理现上…...

亲测解决vscode的debug用不了、点了没反应

这个问题在小虎登录vscode同步了设置后出现,原因是launch文件被修改或删除。解决方法是重新添加launch。 坏境配置 win11 + vscode 解决方法 Ctrl + shift + P,搜索debug添加配置: 选择python debugger。 结果生成了一个文件在当前路径: launch内容: {// Use Int…...

立足智能存取解决方案|HEGERLS智能托盘四向车储存制动能量 实现能源回收

对于商业配送和工业生产的企业而言&#xff0c;如何能高效率、低成本进行低分拣、运输、码垛、入库&#xff0c;用以提升仓库空间的利用效率&#xff0c;是现在大多企业急需要解决的行业痛点。对此&#xff0c;为了解决上述痛点&#xff0c;近年来&#xff0c;物流仓储集成商、…...

2024.2.8日总结(小程序开发5)

对上拉触底事件进行节流处理 在data中定义isloading节流阀 false表示当前没有进行任何数据请求true表示当前正在进行数据请求 在getColors()方法中修改isloading节流阀的值 在刚调用getColors时将节流阀设置true在网络请求的complete回调函数中&#xff0c;将节流阀重置为f…...

Spring Boot配置文件优先级

1、bat文件启动java程序 java -Dmmmqqq -Dfile.encodingUTF-8 -jar ruoyi-admin.jar --mmmiii --llllll 2、配置类型 程序参数Program arguments : --mmmiii 单个属性值&#xff0c;可以从String[] args读取到&#xff0c;放在jar包命令后面 VM参数VM options :一般以-D …...

Rust 初体验1

Rust 初体验 安装 打开官网&#xff0c;下载 rustup-init.exe&#xff0c; 选择缺省模式&#xff08;1&#xff09;安装。 国内源设置 在 .Cargo 目录下新建 config 文件&#xff0c;添加如下内容&#xff1a; [source.crates-io] registry "https://github.com/rus…...

【深度学习】实验7布置,图像超分辨

清华大学驭风计划 因为篇幅原因实验答案分开上传&#xff0c; 实验答案链接http://t.csdnimg.cn/P1yJF 如果需要更详细的实验报告或者代码可以私聊博主 有任何疑问或者问题&#xff0c;也欢迎私信博主&#xff0c;大家可以相互讨论交流哟~~ 深度学习训练营 案例 7 &#xff1…...

【八大排序】归并排序 | 计数排序 + 图文详解!!

&#x1f4f7; 江池俊&#xff1a; 个人主页 &#x1f525;个人专栏&#xff1a; ✅数据结构冒险记 ✅C语言进阶之路 &#x1f305; 有航道的人&#xff0c;再渺小也不会迷途。 文章目录 一、归并排序1.1 基本思想 动图演示2.2 递归版本代码实现 算法步骤2.3 非递归版本代…...

Netty应用(三) 之 NIO开发使用 网络编程 多路复用

目录 重要&#xff1a;logback日志的引入以及整合步骤 5.NIO的开发使用 5.1 文件操作 5.1.1 读取文件内容 5.1.2 写入文件内容 5.1.3 文件的复制 5.2 网络编程 5.2.1 accept&#xff0c;read阻塞的NIO编程 5.2.2 把accept&#xff0c;read设置成非阻塞的NIO编程 5.2.3…...

融资项目——配置redis

一、 在maven中导入相关依赖。在springboot框架中&#xff0c;我们使用spring data redis <!-- spring boot redis缓存引入 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifa…...

npm修改镜像源

背景&#xff1a;切换npm镜像源是经常遇到的事&#xff0c;下面记录下具体操作命令 1. 打开终端运行"npm config get registry"命令来查看当前配置的镜像源 npm config get registry2. 修改成淘宝镜像源"https://registry.npmjs.org/" npm config set re…...

K8S系列文章之 [基于 Alpine 使用 kubeadm 搭建 k8s]

先部署基础环境&#xff0c;然后根据官方文档 K8s - Alpine Linux&#xff0c;进行操作。 将官方文档整理为脚本 整理脚本时&#xff0c;有部分调整 #!/bin/shset -x # 添加源&#xff0c;安装时已经配置 #cat >> /etc/apk/repositories <<"EOF" #htt…...

JVM相关-JVM模型、垃圾回收、JVM调优

一、JVM模型 JVM内部体型划分 JVM的内部体系结构分为三部分&#xff0c;分别是&#xff1a;类加载器&#xff08;ClassLoader&#xff09;子系统、运行时数据区&#xff08;内存&#xff09;和执行引擎 1、类加载器 概念 每个JVM都有一个类加载器子系统&#xff08;class l…...

提升图像分割精度:学习UNet++算法

文章目录 一、UNet 算法简介1.1 什么是 UNet 算法1.2 UNet 的优缺点1.3 UNet 在图像分割领域的应用 二、准备工作2.1 Python 环境配置2.2 相关库的安装 三、数据处理3.1 数据的获取与预处理3.2 数据的可视化与分析 四、网络结构4.1 UNet 的网络结构4.2 UNet 各层的作用 五、训练…...

排序算法---冒泡排序

原创不易&#xff0c;转载请注明出处。欢迎点赞收藏~ 冒泡排序是一种简单的排序算法&#xff0c;其原理是重复地比较相邻的两个元素&#xff0c;并将顺序不正确的元素进行交换&#xff0c;使得每次遍历都能将一个最大&#xff08;或最小&#xff09;的元素放到末尾。通过多次遍…...

基于数据挖掘的微博事件分析与可视化大屏分析系统

设计原理&#xff0c;是指一个系统的设计由来&#xff0c;其将需求合理拆解成功能&#xff0c;抽象的描述系统的模块&#xff0c;以模块下的功能。功能模块化后&#xff0c;变成可组合、可拆解的单元&#xff0c;在设计时&#xff0c;会将所有信息分解存储在各个表中&#xff0…...

数学建模-灰色预测最强讲义 GM(1,1)原理及Python实现

目录 一、GM&#xff08;1&#xff0c;1&#xff09;模型预测原理 二、GM&#xff08;1&#xff0c;1&#xff09;模型预测步骤 2.1 数据的检验与处理 2.2 建立模型 2.3 检验预测值 三、案例 灰色预测应用场景&#xff1a;时间序列预测 灰色预测的主要特点是模型使用的…...

智慧自助餐饮系统(SpringBoot+MP+Vue+微信小程序+JNI+ncnn+YOLOX-Nano)

一、项目简介 本项目是配合智慧自助餐厅下的一套综合系统&#xff0c;该系统分为安卓端、微信小程序用户端以及后台管理系统。安卓端利用图像识别技术进行识别多种不同菜品&#xff0c;识别成功后安卓端显示该订单菜品以及价格并且生成进入小程序的二维码&#xff0c;用户扫描…...

零基础学编程从入门到精通,系统化的编程视频教程上线,中文编程开发语言工具构件之缩放控制面板构件用法

一、前言 零基础学编程从入门到精通&#xff0c;系统化的编程视频教程上线&#xff0c;中文编程开发语言工具构件之缩放控制面板构件用法 编程入门视频教程链接 https://edu.csdn.net/course/detail/39036 编程工具及实例源码文件下载可以点击最下方官网卡片——软件下载—…...

【MySQL进阶之路】MySQL 中表空间和数据区的概念以及预读机制

欢迎关注公众号&#xff08;通过文章导读关注&#xff1a;【11来了】&#xff09;&#xff0c;及时收到 AI 前沿项目工具及新技术的推送&#xff01; 在我后台回复 「资料」 可领取编程高频电子书&#xff01; 在我后台回复「面试」可领取硬核面试笔记&#xff01; 文章导读地址…...

JVM 性能调优 - 常用的垃圾回收器(6)

垃圾收集器 在 JVM(Java虚拟机)中,垃圾收集器(Garbage Collector)是负责自动管理内存的组件。它的主要任务是在程序运行过程中,自动回收不再使用的对象所占用的内存空间,以便为新的对象提供足够的内存。 JVM中的垃圾收集器使用不同的算法和策略来实现垃圾收集过程,以…...

【java】Hibernate访问数据库

一、Hibernate访问数据库案例 Hibernate 是一个在 Java 社区广泛使用的对象关系映射&#xff08;ORM&#xff09;工具。它简化了 Java 应用程序中数据库操作的复杂性&#xff0c;并提供了一个框架&#xff0c;用于将对象模型数据映射到传统的关系型数据库。下面是一个简单的使…...

从零开始手写mmo游戏从框架到爆炸(八)— byte数组传输

导航&#xff1a;从零开始手写mmo游戏从框架到爆炸&#xff08;零&#xff09;—— 导航-CSDN博客 Netty帧解码器 Netty中&#xff0c;提供了几个重要的可以直接使用的帧解码器。 LineBasedFrameDecoder 行分割帧解码器。适用场景&#xff1a;每个上层数据包&#xff0c;使…...

Elasticsearch:BM25 及 使用 Elasticsearch 和 LangChain 的自查询检索器

本工作簿演示了 Elasticsearch 的自查询检索器将非结构化查询转换为结构化查询的示例&#xff0c;我们将其用于 BM25 示例。 在这个例子中&#xff1a; 我们将摄取 LangChain 之外的电影样本数据集自定义 ElasticsearchStore 中的检索策略以仅使用 BM25使用自查询检索将问题转…...

uniapp的api用法大全

页面生命周期API uniApp中的页面生命周期API可以帮助开发者在页面的不同生命周期中执行相应的操作。常用的页面生命周期API包括&#xff1a;onLoad、onShow、onReady、onHide、onUnload等。其中&#xff0c;onLoad在页面加载时触发&#xff0c;onShow在页面显示时触发&#xf…...

笔记——asp.net core 中的 REST

REST&#xff08;reprentational state transfer&#xff0c;表层状态转移&#xff09; REST原则&#xff1a;提倡按照HTTP的语义使用HTTP。 如果一个系统符合REST原则&#xff0c;我们就说这个系统是Restful风格的。 在RPC风格的Web API系统中&#xff0c;我们把服务端的代码…...

排序算法---堆排序

原创不易&#xff0c;转载请注明出处。欢迎点赞收藏~ 堆排序&#xff08;Heap Sort&#xff09;是一种基于二叉堆数据结构的排序算法。它将待排序的元素构建成一个最大堆&#xff08;或最小堆&#xff09;&#xff0c;然后逐步将堆顶元素与堆的最后一个元素交换位置&#xff0c…...

Java字符串(包含字母和数字)通用排序

说明&#xff1a;本文章是之前查到的一篇安卓版的&#xff0c;具体原文路径忘记了。稍微改了一点&#xff0c;挺符合业务使用的&#xff01; 一、看代码 /*** 包含数字的字符串进行比较&#xff08;按照从小到大排序&#xff09;*/private static Integer compareString(Stri…...

【Spring】springmvc如何处理接受http请求

目录 ​编辑 1. 背景 2. web项目和非web项目 3. 环境准备 4. 分析链路 5. 总结 1. 背景 今天开了一篇文章“SpringMVC是如何将不同的Request路由到不同Controller中的&#xff1f;”&#xff1b;看完之后突然想到&#xff0c;在请求走到mvc 之前服务是怎么知道有请求进来…...

2024年安全员-B证证模拟考试题库及安全员-B证理论考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年安全员-B证证模拟考试题库及安全员-B证理论考试试题是由安全生产模拟考试一点通提供&#xff0c;安全员-B证证模拟考试题库是根据安全员-B证最新版教材&#xff0c;安全员-B证大纲整理而成&#xff08;含2024年…...

redis过期淘汰策略、数据过期策略与持久化方式

redis的过期淘汰策略 redis过期淘汰策略有很多,默认是no-eviction 不删除任何数据,内存不足存入会直接报错,可以在redis配置文件中进行设置,其中有两个非常重要的概念,LRU与LFU LRU表示最近最少使用,LFU为最少频率使用 又按照volatile已设置过期时间的数据集和allkeys所有数…...

Oracle Vagrant Box 扩展根文件系统

需求 默认的Oracle Database 19c Vagrant Box的磁盘为34GB。 最近在做数据库升级实验&#xff0c;加之导入AWR dump数据&#xff0c;导致空间不够。 因此需要对磁盘进行扩容。 扩容方法1&#xff1a;预先扩容 此方法参考文档Vagrant, how to specify the disk size?。 指…...

TDengine用户权限管理

Background 官方文档关于用户管理没有很详细的介绍&#xff0c;只有零碎的几条&#xff0c;这里记录下方便后面使用。官方文档&#xff1a;https://docs.taosdata.com/taos-sql/show/#show-users 1、查看用户 show users;super 1&#xff0c;表示超级用户权限 0&#xff0c;表…...