一文解决C/C++中所有指针相关知识点

news2024/11/23 15:18:40

本篇会对C/C++中【常见指针相关知识】一直进行总结迭代,记得收藏吃灰不迷路,一起学习分享喔

请大家批评指正,一起学习呀~

  • 一、指针基本知识
    • 1.1 指针的定义
    • 1.2 (*) 和( &) 运算符
    • 1.3 如何声明指针变量
    • 1.5 指针解决函数间通信问题
  • 二、指针与数组的关系
    • 2.1 指针与整数、指针与指针的加减运算
    • 2.2 数组形参的写法
    • 2.3 指针递增练习
    • 2.4 指针数组和数组指针
      • 数组指针与指针数组的传参使用
    • 2.5 结构指针
    • 2.6 指针的地址、指针的值、指针所指向内容的值
    • 2.7 void指针
    • 2.8 函数指针
  • 三、二级指针(较难喔,坚持住咯)
    • 3.1 二级指针的概念
    • 3.2 二级指针的示例
    • 3.3 二级指针的用途
  • 四、多级指针(万变不离其宗)
  • 五、指针和多维数组
  • 六、指针和字符串的关系

一、指针基本知识

1.1 指针的定义

指针是一个值为内存地址变量(或数据对象)。首先指针是一个变量,它的值就是某个变量的内存地址,就好比 int 类型的变量它的值是整数也是一样的。
从一个例子来着手叭:

#include <stdio.h>
#include <stdlib.h>
int main(void){
	int room = 2;
	//定义两个指针变量指向room
	int *p1 = &room;
	int *p2 = &room;
	printf("room 地址:0x%p\n", &room);
	printf("p1 地址:0x%p\n", &p1);
	printf("p2 地址:0x%p\n", &p2);
	printf("room 所占字节:%d\n", izeof(room));
	printf("p1 所占字节:%d\n", sizeof(p1));
	printf("p2 所占字节:%d\n", sizeof(p2));
	system("pause");
	return 0

示例中定义了一个int类型的变量room,定义了两个指向int类型的指针p1和p2指向room。此时room的地址(&是取地址运算符)printf("room 地址:0x%p\n", &room);就是指针p1和p2的值,但p1和p2的地址又是两个不同的值,跟room的地址完全是两回事儿。

在这里插入图片描述

1.2 (*) 和( &) 运算符

假设有个指向 int 类型的指针ptr:int *ptr;
有个 int 类型的变量:int bat;
假设 ptr = & bat;即 ptr 指向 bat。
此时使用间接运算符或者解引用运算符*后面跟上指针ptr(*ptr)就可以拿到指针指向内存地址上存储的值。上式组合可得:
ptr = & bat;ptr指向bat,即bat的地址赋给了ptr
val = *ptr;val指向ptr的值,即ptr指向地址上的值赋给了val。
(* ptr是指针ptr指向地址上的值,即p的值是一个内存地址是一个变量,它指向的值是* p,是内存地址上存储的值)
===> val = bat;
——————————————————————————————————————
示例:
nurse = 2;
ptr = &nurse;
val = *ptr;
最终得到:
val = 2;
——————————————————————————————————————
总结:
1、&取地址运算符后面跟一个变量名时,就可以拿到该变量的地址。&nurse就可以拿到nurse的地址
2、*解引用运算符后面跟一个指针或者地址的时候,可以拿到该地址上存储的值
3、&取地址运算符*解引用运算符从一定层面上看作是可以相互抵消的

1.3 如何声明指针变量

指针变量的声明必须指定指针指向变量的类型,因为不同类型的变量所占用的内存大小不同。
指针变量声明如下:
int *pi;//pi是指向int类型变量的指针
char *pc;//pc是指向char类型变量的指针

需要注意:
32 位系统中,int 整数占4 个字节,指针同样占4 个字节
64 位系统中,int 整数占4 个字节,指针同样占8 个字节
但这不是个例啦,
在 32 位平台下,无论指针的类型是什么,sizeof(指针名)都是 4.
在 64 位平台下,无论指针的类型是什么,sizeof(指针名)都是 8.

#include <stdio.h>
#include <stdlib.h>
int main(void){
	int room = 2 ;
	int room1 = 3 ;//3p
	int *p1 = &room;
	int *p2 = p1;//int *p2 = &room;
	//1.访问(读、写)指针变量本身的值,和其它普通变量的访问方式相同
	int *p3 = p1;
	printf("room 的地址: %d\n", &room);//6222525
	printf("p1 的值: %d p2 的值: %d\n", p1, p2);//p1 = 6222525,p2 = 6222525
	printf("p3 的值: %d\n", p3);//p3 = 6222525
	p3 = &room1;
	printf("p3 的值: %d, room1 的地址:%d\n", p3, &room1);//不建议用这
	种方式
	//使用16 进制打印,把地址值当成一个无符号数来处理
	printf("p1=0x%p\n", p1);
	printf("p1=0x%x\n", p1);
	printf("p1=0x%X\n", p1);
	system("pause");
	return 0;
}

示例中我们在对指针的值打印的时候一般采用十六进制的%p(ANSIC专门为指针提供的转换说明%p),或者直接采用十六进制0x%x、0x%X打印

1.5 指针解决函数间通信问题

这也是使用指针的主要原因之一,因为被调函数没有办法修改函数的实参,所以只能采用指针的形式将参数的地址传过去,即被调函数中改变主调函数的变量(被调函数中一班不会改变主调函数的值,如果需要的话就要使用指针作为参数)
首先看一个程序示例:需要一个函数交换x和y的值,就需要将x和y的地址作为参数传递给被调函数。

#include <stdio.h>
#include <stdlib.h>
void interchange(int *u,int *v);
int main(void){
	int x = 5,y = 10;
	printf("Originally x = %d and y  = %d\n",x,y);
	interchange(&x,&y);
	printf("Now x = %d and y  = %d\n",x,y);
	system("pause");
	return 0;
}
void interchange(int *u,int *v){
	int temp;
	temp  = *u;
	*u = *v;
	*v = temp; 
}
//output
Originally x = 5 and y  = 10
Originally x = 10 and y  = 5

如此,便能理解为什么输入函数scanf("%d",&num)了,因为它是将读取的值存储到指定的地址上。

二、指针与数组的关系

使用指针的程序会更有效率,尤其在处理数组的时候,而且数组跟指针的关系十分密切,数组名就是数组首元素的地址,假如arr是一个数组,则下式成立:

arr = &arr[0]
arr&arr[0]都是数组首元素的地址(首元素内存地址)
arr 是数组首元素地址,&arr 整个数组的首地址,地址是一样的,只是意义不同。

dates是数组首元素的地址,dates + index 是数组第index个元素dates[index]的地址,*(dates + index)是该元素的值。

数组的地址就是数组首元素的地址

2.1 指针与整数、指针与指针的加减运算

C中指针加1指的是增加一个存储单元,对于数组来讲就是意味着加1后的地址是下一个元素的地址,而不是下一个字节的地址。因为在数组中每个元素所占用的字节大小是固定的,所以指针加1,指针的值递增它所指向类型的大小,比如指向的是int类型的数组,那么指针加1,指针的值直接递增4个字节,也就是指向下一个元素了。以下面short类型数组举例。

请添加图片描述
pti是short类型的指针,所以每次指针加1,pti的值就会递增2个字节,2个字节刚好是一个数组元素的大小,所以指针加1,指针的指向就往下走一步。

总结:
1、 指针加一个数之后与数组之间的关系
dates = &dates[0];
dates + 2 = &dates[2];//相同的地址
*(dates + 2) = dates[2];//相同的值
模板:
dates + n = &dates[n];//相同的地址
*(dates + n) = dates[n];//相同的值

*(dates + n)dates + n 的区别:
*(dates + n):表示dates的第n个元素的值
dates + n:表示dates的第1个元素的值+n

2、指针与整数的运算,指针加减数字表示的意义是指针在数组中位置的移动;对于整数部分而言,它代表的是一个元素,对于不同的数据类型,其数组的元素占用的字节是不一样的,
比如指针+ 1,并不是在指针地址的基础之上加1 个地址,而是在这个指针地址的基础上加1 个元素占用的字节数

  1. 如果指针的类型是char*,那么这个时候1 代表1 个字节地址
  2. 如果指针的类型是int*,那么这个时候1 代表4 个字节地址
  3. 如果指针的类型是float*,那么这个时候1 代表4 个字节地址
  4. 如果指针的类型是double*,那么这个时候1 代表8 个字节地址

3、通用公式:
数据类型 *p;
p + n 实际指向的地址:p 基地址+ n * sizeof(数据类型)
p - n 实际指向的地址:p 基地址- n * sizeof(数据类型)

比如:
1)对于int 类型,比如p 指向0x0061FF14,则:
p+1 实际指向的是0x0061FF18,与p 指向的内存地址相差4 个字节;
p+2 实际指向的是0x0061FF1C,与p 指向的内存地址相差8 个字节
2)对于char 类型,比如p 指向0x0061FF28,则:
p+1 实际指向的是0x0061FF29,与p 指向的内存地址相差1 个字节;
p+1 实际指向的是0x0061FF2A,与p 指向的内存地址相差2 个字节;

4、指针与指针之间的加减运算
我们先总结再看示例,知识点:
(1)指针和指针可以做减法操作,但不适合做加法运算;
(2)指针和指针做减法适用的场合:两个指针都指向同一个数组,相减结果为两个指针之
间的元素数目,而不是两个指针之间相差的字节数。

比如
int int_array[4] = {12, 34, 56, 78};
int *p_int1 = &int_array[0];
int *p_int2 = &int_array[3];
p_int2 - p_int1 的结果为3,即是两个指针之间的元素数目为3 个。
如果两个指针不是指向同一个数组,它们相减就没有意义。

3)不同类型的指针不允许相减
比如:
char *p1;
int *p2;
p2-p1 是没有意义的。

2.2 数组形参的写法

在函数原型和函数定义中,可以使用 int arr[] 代替 int * arr
int arr[] 和 int * arr 两种形式都表示arr是一个指向 int 类型的指针。如下图所示中列举了很多诸多相似的写法,一起学习一下。
请添加图片描述
接下来分别演示用数组表示法和指针法进行数组求和运算。数组表示法就是将整个数组作为参数传递,指针表示法就是将数组名也就是首元素地址或者说是指针作为参数传递。
1、首先用数组表示法进行求和

int main(void){
	int marble[10] = {……};//省略不写啦
	int answer = sum(marble,10);
	printf("%ld",answer);
}
int sum(int arr[],int N){
	int total = 0;
	for(int i = 0;i < 10;i++){
		total += arr[i];
	}
	return total;
}

2、首先用指针表示法进行求和

int main(void){
	int marble[10] = {……};//省略不写啦
	int answer = sum(marble,marble + 10);
	printf("%ld",answer);
}
int sum(int *start,int *end){
	int total = 0;
	while(start < end){
		total += *start;
		start++;
	}
	return total;
}

start++递增指针变量start是指向数组的下一个元素,因为start是指向int的指针,所以start+1相当于其值递增int类型的大小。

2.3 指针递增练习

1、total = *start ++total = *++start;这两个语句是非常常见且非常重要的。(++* 的优先级相同

2、total = *start ++;表示:先将指针指向位置上的值赋给total,然后在递增指针

3、total = *++start ;表示:先递增指针,再将指针指向的值赋给total

经典练习:

#include <stdio.h>
int data[2] = {100,200};
int moredata[2] = {300,400};
int main(void){
	int * p1,*p2,*p3;
	p1 = p2 = data;
	p3 = moredata;
	printf("*p1 = %d,*p2 = %d, *p3 = %d\n",*p1,*p2,*p3);
	printf("*p1++ = %d,*++p2 = %d, (*p3)++ = %d\n",*p1++,*++p2,(*p3)++);
	printf("*p1 = %d,*p2 = %d, *p3 = %d\n",*p1,*p2,*p3);
}

输出:

请添加图片描述
第一行输出应该是没有问题的,因为:
p1 = p2 = data;
p3 = moredata;
所以:
p1 = p2 = data = &data[0];->*p1 = *p2 = *data = *(&data[0]) = &data[0] = 100;
p3 = moredata; ->*p3 = *moredata = *(&moredata[0]) = moredata[0] = 300;

第二行输出:

*p1++:是先打印p1所指地址上的值,在进行递增。所以结果为:p1所指地址上的值100,但展示结果之后p1指针便已自增,指向data[1]上
*++p2:先进行指针递增,p2指向data[1]上,在输出指针指向位置上的值200
(*p3)++:先将p3指向位置的值输出300,在进行值的递增

因为来到第三行:

*p1 = 200,*p2 = 200,*p3 = 301

注意:
1、*p1++(*p1)++是不同滴,虽然++* 的优先级相同,但是结合律有顺序,是从右向左的,所以*p1++是先执行p1++再执行*p1的。total = *p1++先将p1指向的值赋给total,但还是先进行p1++,因为根据自增运算规律可知,p1++之后并不会立刻改变值,而是先使用再递增嘛,所以它跟(*p1)++不同,前者++的时候是指针递增,而后者递增的时候是值的递增。

2、P++(P是指针)的概念是在P当前地址的基础上,自增P对应类型的大小,即P = P+1*(sizeof(类型))

2.4 指针数组和数组指针

想要理解指针数组和数组指针的区别,很简单。来看两个小练习就明白辽。
根据题目要求,正确的声明变量:
A:psa是一个内含20个元素的数组,每个元素都是指向int的指针。
这种我们将其称为指针数组,即装着指针的数组int *(p1[20]);

定义:类型 * (指针数组名[元素个数])

其中p1是数组名称
如下图所示:int * (p1[5]),数组p1内含5个int类型的指针
在这里插入图片描述


指针数组的示例:

#include <stdio.h>
#include <stdlib.h> 
int main(void){ 
	//二维矩阵中找到身高最高和次高的值
	int girls[4][3] = { 
		{173, 158, 166}, 
		{168, 155, 171}, 
		{163, 164, 165}, 
		{163, 164, 172} };
	//定义一个有两个元素的指针数组,每个元素都是一个指针变量
	//定义两个指针放进指针数组中,让他们分别指向最高和次高的地址
	//qishou[0]中最高的地址,qishou[1]中次高的地址
	//同理如果要找出前十个身高最高的,直接将2换成10即可
	int* (qishou[2]);
	//base case 先通过前两个身高分别定出最高和次高放入指针数组中
	if (girls[0][0] > girls[0][1]) { 
		qishou[0] = &girls[0][0];//最高 
		qishou[1] = &girls[0][1]; //次高
	}
	else { 
		qishou[0] = &girls[0][1]; //最高 
		qishou[1] = &girls[0][0];  //次高
	}
	//让其他元素与最高和次高进行比较,总共12个元素
	for (int i = 2; i < 12; i++) {
		//girls[i/3][i%3] 非常巧妙的一个循环就可以遍历二维数组的方法
		//如果新身高小于等于此身高就直接略过
		if(*qishou[1] >= girls[i/3][i%3]){ 
			continue; 
		}
		//候选者高于次高
		//1.候选者比"冠军"矮 
		if(girls[i/3][i%3] <= *qishou[0]){ 
			qishou[1] = &girls[i/3][i%3]; 
		}else { 
			//2.候选者比"冠军"高 
			qishou[1] = qishou[0]; 
			qishou[0] = &girls[i/3][i%3]; 
		} 
	}
	printf("最高的身高: %d , 次高的身高: %d\n", *qishou[0], *qishou[1]);
	system("pause");
	return 0; 
}

在这里插入图片描述


tips:插播一个小知识点:一个for循环便利二维数组
在这里插入图片描述


B:p1是一个指向数组的指针,数组内含有20个char类型的值。
这种我们将其称为数组指针,即指向数组的指针int (*p1)[20];

定义:类型 (*数组指针名)[元素个数]

其中p1是指针名称
如下图所示:int (*p2)[5],指针p2指向内含5个int类型数据的数组
在这里插入图片描述


数组指针的示例:


数组指针与指针数组的传参使用

2.5 结构指针

结构指针请参考这边喔~C语言复合类型之结构(struct)篇(结构指针)

2.6 指针的地址、指针的值、指针所指向内容的值

请添加图片描述
图中可以总结出:
1、p的值就是i的地址&i
2、*p就是指针所指向内存单元的数据,即指针所指向内存地址上存储的值
3、&p指指针本身的地址
4、&*p的值跟p是一样的,都是i的地址&i

2.7 void指针

2.8 函数指针

三、二级指针(较难喔,坚持住咯)

只要理解了上面指针的一些性质,相信我们一定可以顺水推舟推敲出二级指针是个什么玩意儿哈哈哈。

3.1 二级指针的概念

二级指针也是一个普通的指针,只是二级指针的值是一级指针的地址罢了。
一级指针:指向一个普通变量,并保存该普通变量的地址;
二级指针:指向一个一级指针,并保存该一级指针的地址;

int guizi1 = 888;
int *guizi2 = &guizi1; //1 级指针,保存guizi1 的地址
int **liujian = &guizi2; //2 级指针,保存guizi2 的地址,guizi2 本身是一个一级指针变量

3.2 二级指针的示例

刘建手里持有第一个柜子的地址
第一个柜子里面是第二个柜子的地址
第二个柜子里面是第三个柜子的地址
第三个柜子里面放着888

在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>
int main(void){
	int guizi2 = 888; //存枪的第3个柜子
	int *guizi1 = &guizi2; //存第3 个柜子地址的第2个柜子
	int **liujian = &guizi1; //手握第一个柜子地址的刘建
	printf("刘建打开第一个柜子,获得第二个柜子的地址:0x%p\n", *liujian);
	printf("guizi2 的地址:0x%p\n", &guizi2);
	int *tmp;
	tmp = *liujian;
	printf("访问第二个柜子的地址,拿到枪:%d\n", *tmp);
	printf("刘建一步到位拿到枪:%d\n", **liujian); //缩写成**liujian
	system("pause");
	return 0;
}

请添加图片描述
结果分析:
int guizi2 = 888; //存枪的第3 个柜子
int *guizi1 = &guizi2; //存第3 个柜子地址的第2个柜子
int **liujian = &guizi1; //手握第一个柜子地址的刘建


二级指针的解引用【重点知识】:

1、二级指针liujian的一次解引用 **liujian就可以得到被指向指针的地址;
2、二级指针进行两次解引用就可以得到所指的一级指针所指地址的值;
第一次解应用:*liujian = guizi1 = &guizi2
第二次解引用:![请添加图片描述](https://img-blog.csdnimg.cn/b067977535c74fe7894305bfe0d43440.png)


则:
请添加图片描述
**liujian一步到位的取法可以直接得到二级指针所指以及指针地址上的值。
二级指针的解引用非常重要,需要牢记!!

3.3 二级指针的用途

  1. ==一级指针可以将主调函数中的变量通过参数“带入”被调函数内部进行修改,但没办法将被调函数中的内部变量“带出”到主调函数中

我们知道使用指针可以在被调函数中修改主调函数中变量的值,如下:
在这里插入图片描述
但是想要把被调函数中的内部变量“带出”到主调函数中需要用到双指针,如下所示,被调函数 boy_home中的内部变量boy拿到主调函数中进行打印
在这里插入图片描述
其中*meipo = &boy;表示将二级指针的值,即一级指针的来存储boy的地址
最后通过printf("boy: %d\n", *meipo);中的*meipo拿到一级指针地址上的值23
2. 二级指针可以不但可以将变量通过参数”带入“函数内部,也可以将函数内部变量“带出”到函数外部。

四、多级指针(万变不离其宗)

工作中二级指针时有见到,多级指针其实已经很少啦
声明办法如下:
int guizi1 = 888;
int *guizi2 = &guizi1; //普通指针
int **guizi3 = &guizi2; //二级指向一级
int ***guizi4 = &guizi3; //三级指向二级
int ****guizi5 = &guizi4; //四级指向三级
……
在这里插入图片描述

五、指针和多维数组

六、指针和字符串的关系

指针在字符串定义时的作用
指针的地址和指针的值,两者的区别,用p328页处的的例题来进行说明

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

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

相关文章

使用omp并行技术加速bfs广度优先算法

基本思想 从初始状态S开始&#xff0c;利用规则&#xff0c;生成所有可能的状态。构成树的下一层节点&#xff0c;检查是否出现目标状态G&#xff0c;若未出现&#xff0c;就对该层所有状态节点&#xff0c;分别顺序利用规则。生成再下一层的所有状态节点&#xff0c;对这一层的…

chatgpt赋能python:Python在SEO中的排名

Python在SEO中的排名 Python作为一门高级编程语言&#xff0c;已经有近三十年的历史&#xff0c;被广泛用于各个领域的开发&#xff0c;包括 Web开发、数据分析、机器学习等。在 SEO 中&#xff0c;Python 也具有很高的应用价值。本文将会介绍 Python 在 SEO 中的应用以及其排…

C语言进阶教程(一个可执行文件生成的具体步骤)

文章目录 前言一、预处理二、编译三、汇编四、链接总结 前言 本篇文章来讲解一个.c文件生成一个可执行文件的完整过程&#xff0c;我们学习了那么久&#xff0c;只知道在编译器中按下编译运行就可以将一个.c文件运行起来了&#xff0c;但是我们并不了解其中的具体步骤&#xf…

【openGauss简单数据库管理---快速入门】

【openGauss简单数据库管理---快速入门】 &#x1f53b; 一、openGauss数据库管理&#x1f530; 1.1 连接openGauss数据库&#x1f530; 1.2 创建数据库&#x1f530; 1.3 查看数据库和切换数据库&#x1f530; 1.4 修改数据库&#x1f530; 1.5 删除数据库&#x1f530; 1.6 启…

高等代数复习(二)

本篇复习内容有 求解标准正交基 证明标准正交基 证明正交变换 利用共轭变换证明 求解与给定矩阵的相似矩阵--对角矩阵 1.求标准正交基 在求标准正交基时&#xff0c;通常要先正交化&#xff0c;然后单位化&#xff0c;即可求出标准正交基。 2.证明标准正交基 标准正交基单位…

chatgpt赋能python:Python提取指定位置字符

Python 提取指定位置字符 Python 是一种高级程序语言&#xff0c;其易读性、简单易学性和易维护性使其成为最受欢迎的编程语言之一。它可以用于各种数据分析和科学计算&#xff0c;包括搜索引擎优化&#xff08;SEO&#xff09;。 在SEO中&#xff0c;提取和处理数据是一个重…

C++——string容器模拟实现

目录 1. 基本成员变量 2. 默认成员函数 2.1 构造函数 2.2 析构函数 2.3 拷贝构造函数 2.4 赋值运算符重载 3. 容量与大小相关函数 3.1 size 3.2 capacity 4. 字符串访问相关函数 4.1 operator[ ]重载 4.2 迭代器 5. 增加函数接口 5.1 reserve 5.2 resize 5.3 …

【二叉树part01】| 二叉树的递归遍历、二叉树的迭代遍历

目录 ✿二叉树的递归遍历❀ ☞LeetCode144.前序遍历 ☞LeetCode145.二叉树的后序遍历 ☞LeetCode94.二叉树的中序遍历 ✿二叉树的迭代遍历❀ ☞LeetCode144.前序遍历 ☞LeetCode145.二叉树的后序遍历 ☞LeetCode94.二叉树的中序遍历 ✿二叉树的递归遍历❀ ☞LeetCode…

docker-compose启动opengauss数据库——华为“自研”数据库

文章目录 1. 启动数据库2. 登录2.1 本地登录2.2 远程登录 1. 启动数据库 yml文件 创建opengauss目录&#xff0c;里边创建docker-compose.yml文件内容如下&#xff1a; 华为开源数据库&#xff0c;默认5432端口&#xff0c;是不是很熟悉&#xff0c;疑似又是个套壳子的事件。果…

Cortext-M3系列:调试系统架构(8)

1、调试特性概述 单片机的调试功能在程序开发中有着十分重要的地位&#xff0c;好的调试工具&#xff0c;能让程序开发大大加快。笔者在刚开始学单片机相关知识时&#xff0c;使用的是pintf打印相关参数&#xff0c;进行调试&#xff08;虽然现在很多时候也这样&#xff09;&am…

MyBatis 的使用方法

观前提示:本篇博客演示使用的 IDEA 版本为2021.3.3版本,使用的是Java8(又名jdk1.8) 前端使用 VSCode(Visual Studio Code1.78.2) 电脑使用的操作系统版本为 Windows 10 目录 Mybatis是什么? Mybatis 有什么用? Mybatis 框架交流 Mybatis 项目环境搭建 1. 添加 Mybatis…

设计模式之生成器(建造者)模式笔记

设计模式之建造者模式笔记 说明Builder(生成器)目录UML生成器(建造者)模式示例类图自行车类建造者抽象类摩拜单车对象类小黄车单车对象类指挥者类测试类优缺点 模式扩展手机类测试类 说明 记录下学习设计模式-生成器(也叫建造者)模式的写法。 Builder(生成器) 意图:将一个复…

监控中的计算机科学

文章目录 一、前言二、监控分类2.1 模拟摄像头2.1 数字摄像头 三、监控系统四、后端产品4.1 硬盘录像机4.2 视频矩阵4.3 控制设备4.4 显示设备 五、传输端5.1 光纤视频线5.1.2 单模光纤5.1.3 多模光纤5.1.4 光端机 5.1 双绞线 六、畅享 一、前言 布林肯访华&#xff0c;黑我们…

Redis6之事务与锁

事务 Redis事务是一个单独的隔离操作&#xff1a;事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中&#xff0c;不会被其他客户端发送来的命令请求所打断。 Redis事务的主要作用就是串联多个命令防止别的命令插队。 命令 1、开启事务&#xff1a;multi 2、执行事…

STM32 RGB屏幕

使用ST的HAL库进行开发&#xff0c;RGB屏幕是480*272的4.3寸LCD&#xff0c;由于驱动RGB屏幕需要较多的内存&#xff0c; 所以使用了外部SDRAM&#xff0c;内存是32M字节&#xff0c;关于SDRAM的驱动本文不进行讨论。 RGB屏幕常用的像素格式有&#xff1a;ARGB8888、RGB888、…

Vue----Vue项目的目录结构

【原文链接】Vue----Vue项目的目录结构 Vue 项目的目录结构 VUE项目的目录结构如下所示 .vscode VSCode工具的配置文件&#xff0c;和VUE项目没有什么关系 node_modules VUE项目运行依赖文件&#xff0c;通过npm install 安装的文件即存放在此文件夹 public 资源文件夹&am…

【现代密码学】(网安)期末复习笔记

现代密码学 【考后感悟】还是得注重简答题&#xff0c;需每个密码算法都要有所了解&#xff08;有些难的可以不用了解完整算法过程&#xff0c;估计考不上&#xff1f;&#xff09;&#xff0c;并对几个重要密码算法&#xff08;重点下面会讲&#xff09;着重复习&#xff08;会…

部署kubernets v1.27.3集群

本文将演示如何使用kubeadm快速部署一个Kubernetes v1.27.1集群&#xff0c;并会简单说明如何在集群上部署nginx容器 主机环境预设 本示例中的Kubernetes集群部署将基于以下环境进行。 OS: Ubuntu 20.04 Kubernetes&#xff1a;v1.27.3 Container Runtime: Docker CE 23.0.…

【并发编程】深入探索AQS

文章目录 一、AQS 介绍二、通过ReentrantLock分析AQS的实现2.1、获取锁流程2.2、获取锁源码分析2.2.1、acquire2.2.2、tryAcquire2.2.3、addWaiter2.2.4、acquireQueued2.2.5、shouldParkAfterFailedAcquire 2.3、解锁源码分析2.3.1、unlock2.3.2、release2.3.3、tryRelease2.3…

实验篇(7.2) 17. 站对站安全隧道 - FortiGate作为SSL客户端(SSL) ❀ 远程访问

【简介】虽然常用的站到站的连接用的是IPsec VPN&#xff0c;但是在某些特殊情况下&#xff0c;UDP500或4500端口被阻断&#xff0c;IPsec VPN无法连接&#xff0c;那么还有其它办法实现站到站的连接吗&#xff1f;SSL VPN也可以的。 实验要求与环境 OldMei集团深圳总部部署了域…