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

[C/C++]指针详讲-让你不在害怕指针

  •  个人主页:北·海
  •  🎐CSDN新晋作者
  •  🎉欢迎 👍点赞✍评论⭐收藏
  • ✨收录专栏:C/C++
  • 🤝希望作者的文章能对你有所帮助,有不足的地方请在评论区留言指正,大家一起学习交流!🤗

目录

前言

 一.&与*的作用与结合方向

二.指针和数组的关系

1.利用指针访问数组里的值

2.利用指针将数组作为实参传递给函数

 三.字符指针与字符数组

四.指针在内存分配中的应用

1.用C语言中的malloc在堆区分配动态内存

1.用C++中的new在堆区分配动态内存

五.使用指针为什么能提高程序的性能

六.指针与const搭配的四种情况

七.引用是实现原理

八.多级指针

九. 指针和函数的关系

1.通过指针使函数返回多个值

2.函数指针

3.函数的返回值类型为指针类型

十.指针和结构体的关系

 


前言

指针在编程语言中扮演着重要的角色,特别是在C语言中。指针提供了直接访问和操作内存地址的能力,使得编程更加灵活、高效,并且可以处理各种复杂的数据结构和算法。

以下是指针的几个重要方面和作用:

  1. 内存管理:指针允许程序直接与内存交互。通过使用指针,可以动态地分配和释放内存,避免了静态内存分配所带来的限制。这在处理动态数据结构(如链表、树、图等)和大规模数据中非常有用。

  2. 传递参数和引用:通过指针,可以在函数之间传递参数和引用。传递指针作为函数参数,可以避免在函数调用时产生副本,节省了内存和时间开销。此外,指针还可以用于函数返回多个值或修改调用者的变量。

  3. 动态数据结构:动态数据结构如链表、树、堆等通常需要使用指针进行内存分配和组织。指针可以在运行时创建、删除、连接和重新组织数据结构,使得数据结构的管理更加灵活和高效。

  4. 数组和字符串操作:在C语言中,数组实际上是通过指针来访问和操作的。指针使得数组可以直接访问和修改其元素,还可以进行指针算术操作,实现数组的遍历和操作。字符串在C语言中本质上是以空字符结尾的字符数组,指针的使用是对字符串进行处理的关键。

  5. 性能优化:指针的使用可以提高程序的性能。通过使用指针来访问和操作数据,可以减少副本的生成和数据的复制,提高程序的执行效率。


 一.&与*的作用与结合方向

作用: &在等号的右边为取地址符号,在等号的左边为引用符号

         *可以用做为乘号,也可用作为对指针变量解引的符号,取该地址存放的数据

结合方向:

“&”和“*”都是右结合的。假设有变量 x = 1,则*&x 的含义是,先获取变量 x 的地址,再获取地址中的内容。因为“&”和“*”互为逆运算,所以 x = *&x。

例如:输入 x、y 两个整数,然后将其中的值大的赋值给 x,小的赋值给 y。即:假设输入 x = 8,y = 9。就将 9 赋值给 x,8 赋值给 y。

void main(){//声明两个普通变量int x, y;//声明两个指针变量int *px, *py;//声明一个临时变量,用于交换int t;//输入两个值,赋值给 x、yscanf("%d", &x);scanf("%d", &y);//给指针变量 px、py 赋初值(关联变量 x、y)px = &x;py = &y;//利用指针来对比 x、y 的值,如果 x 的值比 y 的值小,就交换if(*px < *py){//交换步骤,其中*px == x、*py == yt = *px;*px = *py;*py = t;}printf("x =  %d, y = %d", *px, *py);
}

二.指针和数组的关系

1.利用指针访问数组里的值

	//利用指针访问数组里面的值int nums[] = {1,2,3,4};//方法一:下标法cout << "第一个数 :" << nums[0] << endl;//方法二:指针法cout << "第一个数 :" << *(nums + 0) << endl;//数组名就是数组元素的首地址

2.利用指针将数组作为实参传递给函数

void Test1(int nums[],int n) {for (int i = 0; i < n; i++) {cout << nums[i] << " ";}
}int main() {//利用指针访问数组里面的值int nums[] = {1,2,3,4};int* p = nums;//利用指针将数组作为实参传递给函数Test1(nums, 4);//数组名就是数组元素的首地址//方法二Test1(p, 4);//p指向数组,再将指向数组的指针传给被调函数
}

补充对指针加一 : 例如p++,不会将地址的值加一,而是将数组下移一位

 三.字符指针与字符数组

C语言中,没有字符串类型的变量,通常用字符数组或者字符指针存放字符串

1.字符数组的声明

	char str[] = "C++";char str1[] = { 'C','+','+' ,'\0'};字符数组的声明方式,在使用第二种声明方式的时候,必须在最后加上\0,此符号代表在这个地方该数组就结束了,如果不加该符号,会访问出界的

  字符数组的访问

	char str[] = "C++";char str1[] = { 'C','+','+' ,'\0'};printf("%s\n", str1);//%s格式化,表示直接输出整个数组printf("%c\n", str[0]);//利用数组法取str第一个字符printf("%c\n", *(str1 + 1));//利用指针法取str1的第2个字符

由上面可以看出,可以通过%c一个字符一个字符的输出,那么也可也利用循环输出每个字符

	for (int i = 0; i < strlen(str); i++) {printf("%c", str[i]);}

还可以用过strlen(str)或者sizeof(str)/sizeof(char)来获取该数组的长度

2.字符指针的声明

char *word = "have a good night";

  字符指针的访问

	const char* word = "have a good night";printf("%s\n", word);printf("%c\n", word[0]);for (int i = 0; i < strlen(word); i++) {printf("%c", word[i]);}

    对字符指针地址的加减

	const char* word = "have a good night";word++;printf("%s\n", word);//此时就会将指针下移到第一个a的地方,从a的地方进行输出,输出为:ave a good nightword--;printf("%s\n", word);//输出为:have a good nightconst char str[] = "C++";str++;//报错,在字符数组中不能进行加减操作,表达式必须是可修改的左值printf("%s", str);

四.指针在内存分配中的应用

1.用C语言中的malloc在堆区分配动态内存

1.利用malloc创建一维数组

#include <iostream>
#include <stdlib.h>
using namespace std;
int main() {int n;int* p = nullptr;cout << "请输入要存放的数据个数:";cin >> n;//在堆区分配内存p = (int *)malloc(n * sizeof(int));//输入for (int i = 0; i < n; i++) {cin >> *(p+i);}//输出for (int i = 0; i < n; i++) {cout << *(p+i) << " ";}free(p);
}

用malloc进行分配,注意malloc的返回值类型位void*类型,需要进行强制类型转换,由于在堆区分配的动态内存,所以在使用完之后,为了防止内存泄漏,需要用free进行释放

2.利用malloc进行开辟二位数组,与释放二位数组

#include <iostream>
#include <stdlib.h>
using namespace std;
int main() {int row = 0 ,col = 0 ;int** p = nullptr;cout << "依此输入行和列:" << endl;cin >> row>>col;//在堆区分配内存p = (int **)malloc(row * sizeof(int*));for (int i = 0; i < row; i++) {*(p + i) = (int*)malloc(col * sizeof(int));}//输入for (int i = 0; i < row * col; i++) {cin >> p[i / col][i % col];}//输出for (int i = 0; i < row * col; i++) {cout << p[i / col][i % col] << " ";}//释放动态开辟的二维数组for (int i = 0; i < row; i++) {free(p[i]);}free(p);
}

原理是,先创建一个指针数组,然后在利用改一级指针去创建动态int类型数组,在输入时候,用到了一个小技巧,用一层循环给二维数组赋值,在使用二维数组时候,应该先将每一层一级指针指向的内存块释放掉,然后再去释放该释放二级指针本身指向的内存块

1.用C++中的new在堆区分配动态内存

用到C++中的new分配内存,用delete释放内存,这里的new和delete只适用于c++中,malloc与free适用于c/c++,直接上例子

1.使用new进行分配一个动态的一维数组

int main() {int n;cout << "输入数组的大小:";cin >> n;int* p = new int[n];//输入for (int i = 0; i < n; i++) {cin >> *(p + i);}//输出for (int i = 0; i < n; i++) {cout << *(p + i) << " ";}delete[]p;
}

2.创建二维数组

int main() {int rows = 3;int cols = 4;// 创建动态二维数组int** array = new int*[rows];  // 创建一级指针数组for (int i = 0; i < rows; i++) {array[i] = new int[cols];  // 创建二级指针数组}// 使用动态二维数组for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {array[i][j] = i * cols + j;  // 给数组元素赋值}}// 打印动态二维数组for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {std::cout << array[i][j] << " ";}std::cout << std::endl;}// 释放动态二维数组的内存for (int i = 0; i < rows; i++) {delete[] array[i];  // 释放二级指针数组}delete[] array;  // 释放一级指针数组return 0;
}

和malloc的原理都是一样的,起始可以将一维数组创建的长一点,利用p[i / col][i % col];完全可以将一位数组当二维数组用,二维数组的存储方式也是按行存储的,地址都是连续的

在使用delete时候,数组的释放格式为 delete []p;,单个变量的释放格式为 delete p;

五.使用指针为什么能提高程序的性能

  • 直接访问内存:指针允许直接访问和操作内存中的数据。相比于通过变量的拷贝进行操作,直接访问内存可以减少数据的复制和移动,从而提高程序的执行效率。

#include <iostream>
using namespace std;
void Test1(int *p) {(*p)++;
}
void Test2(int m) {m++;
}
int main() {int num1 = 10,num2=10;Test1(&num1);cout << "Test1 :" << num1 << endl;//输出结果11Test2(num2);cout << "Test2 :" << num2 << endl;//输出结果10
}

Test1通过直接访问内存,避免了数据的拷贝和移动,提高了程序的执行效率。

Test2函数通过传递值的拷贝来操作变量。当我们调用该函数后,原始变量的值保持不变

  • 减少内存和时间开销:通过传递指针作为函数参数,可以避免在函数调用时产生变量的副本,从而减少内存的使用和传输的时间开销。特别是在处理大型数据结构或大量数据时,使用指针可以显著减少内存和时间的消耗。

  • 动态内存分配:指针使得动态内存分配成为可能,即在程序运行时根据需要分配和释放内存。相比于静态内存分配,动态内存分配可以更灵活地管理内存,避免内存浪费和限制,并且减少了程序启动时的内存占用。

六.指针与const搭配的四种情况

  • const 写在int之前,则限定不能通过*指针去改变该指针指向的值,但是可以指向别的指针
  • const 写在int之后,则限定可以通过*指针去改变该指针指向的值,但是不能指向别的指针
  • 两个const一个写在int前,一个写在变量名前,限制指针不能指向别的指针,并且不允许修改指针指向的值
  • 总结 : 看const离类型(int)近,还是理变量名近,离谁近,就修饰谁,谁就不能变
#include<iostream>
using namespace std;int main() {int wife = 30;int girl = 18;//第一种 : 渣男型,普通指针可以随意更改指向与指向地址的值int* zha_nan = &wife;cout << *zha_nan << endl;zha_nan = &girl;cout << *zha_nan << endl;//第二种 : 直男型,以自我为中心,可以改变指向,但是不可以改变指向的地址的值const int* zhi_nan = &wife;//*zhi_nan = 25;//报错,不能改变值zhi_nan = &girl;cout << *zhi_nan << endl;//第三种 : 暖男型,专一,不可以改变指向,但是可以改变指向的地址的值int* const nuan_nan = &wife;//nuan_nan = &girl;//报错,不能改变指向*nuan_nan = 25;cout << *nuan_nan << endl;//第四种 : 超级暖男型,超级专一,不能改变指向,也不能改变指向地址的值const int* const _super_nuan_nan = &wife;//*_super_nuan_nan = 25;//报错,不能改变指向地址的值//super_nuan_nan = &girl;//报错,不能改变指向//总结 : const理谁近就修饰谁,理(int)近,则修饰该指针的值不能改变,修饰变量,//	    则该指针不能在指向别的变量了
}

七.引用是实现原理

引用的底层也是用指针进行实现的

	int a = 0;int b = 2;int& c = a;c = b;//c是a的别名,将b的值赋值给c,就相当于将b的值也赋值给了acout << c << endl;//2cout << a << endl;//2//引用变量只能初始化一次,很像 int* const c = a;//该指针也只能进行一次初始化,就可以猜测引用的底层也是用该类型指针实现的

在使用引用的时候,编辑器会将引用类型转换为int * const 类型

例子:

void swap1(int& a, int& b) {int temp = a;a = b;b = temp;
}
void swap2(int* const a,int* const b) {int temp = *a;*a = *b;*b = temp;
}
int main() {int a = 1;int b = 2;swap1(a, b);//引用实现cout << "a = " << a << " b = " << b << endl;//a = 2,b =1swap2(&a, &b);cout << "a = " << a << " b = " << b << endl;//a = 2,b =1
}

对照swap1和swap2,在形参方面,引用变量会被改为int * const类型,在实参方面会将传入整数改为传入地址

八.多级指针

举例二级指针,懂了引用变量的话,那么对二级指针就可以有个优化了,提出指针引用,代码如下:

void home(int * p) {int b = 12;p = &b;
}
int main() {int a = 10;int* p = &a;//让p存放b的地址home(p);cout << *p << endl;//10
}

可以看出以上代码是无法改变p的指向的,改变值需要用一级指针,改变一级指针的指向需要用到二级指针,一次类推,这里直接就不写二级指针了,直接用一级指针的引用代替二级指针

void home(int *& p) {int b = 12;p = &b;
}
int main() {int a = 10;int* p = &a;//让p存放b的地址home(p);cout << *p << endl;//12
}

由此可以看出,利用指针引用可以将p的指向改变,这也的引用可以增强代码的可读性,与简洁性

九. 指针和函数的关系

1.通过指针使函数返回多个值

比如给你了一个已经初始化的数组,需要定义一个函数,用于返回这个数组的最大值与次大值,这个时候,为了增强代码的可读性,尽量返回一个数组,因为当返回的数据多了,也只能用返回数组实现了,代码如下:

void _max(int *nums,int n,int* exterm) {exterm[0] = nums[0];exterm[1] = nums[0];for (int i = 0; i < n; i++) {//大于次大的if (nums[i] > exterm[1]) {if (nums[i] > exterm[0]) {//大于最大的exterm[1] = exterm[0];exterm[0] = nums[i];}if (nums[i] < exterm[0]) {//小于最大的exterm[1] = nums[i];}}}
}int main() {//求该数组中的最大值与次大值int nums[] = { 2,6,4,9,5 };int exterm[2] = { 0 };_max(nums, 5, exterm);cout << exterm[0] << " " << exterm[1] << endl;//9,6
}

2.函数指针

函数指针是指向函数的指针变量。它可以存储函数的地址,并允许我们通过该指针调用相应的函数。函数指针在C和C++中都有广泛的应用,可以用于回调函数、函数参数以及实现函数的动态调用等场景。

要理解函数指针,首先需要了解函数的定义和函数指针的声明以及函数指针的使用方式。

1.函数定义:
返回类型 函数名(参数列表) {// 函数体
}2.函数指针的声明:
返回类型 (*指针变量名)(参数列表);指针变量名:函数指针的名称。
*:用于指明该变量是一个指针。
返回类型:函数指针指向的函数的返回类型。
参数列表:函数指针指向的函数的参数列表。3.将函数指针指向函数
指针变量名 = 函数名;4.通过函数指针调用函数:
(*指针变量名)(参数列表);//方法一
(指针变量名)(参数列表);//方法二

举例:

#include <iostream>int add(int a, int b) {return a + b;
}int subtract(int a, int b) {return a - b;
}int main() {// 声明函数指针int (*p)(int, int);// 将函数指针指向add函数p = add;// 通过函数指针调用add函数int result = (*p)(10, 5);std::cout << "Add: " << result << std::endl;// 将函数指针指向subtract函数p = subtract;// 通过函数指针调用subtract函数result = (*p)(10, 5);std::cout << "Subtract: " << result << std::endl;return 0;
}

3.函数的返回值类型为指针类型

int* creat() {return new int(1);//创建一个int类型的变量初始化为1,动态分配的数组不能进行初始化	
}int main() {//函数的返回值类型为指针变量类型,例子,//在creat函数里面动态的分配内存,将指向该段内存的指针返回int* p = creat();cout << "*p :" << *p << endl;//*p : 1delete p;
}

十.指针和结构体的关系

利用指针访问结构体里面的值

struct Test{int a;int b;int c;};struct Test ss = { 2,3,4 };//声明了结构对象ss,并把ss 的成员初始化为2,3 和4。struct Test* ptr = &ss;//声明了一个指向结构对象ss 的指针。它的类型是//Test *,它指向的类型是Test 。printf("%d", ptr->a);printf("%d", ptr->b);printf("%d", ptr->c);

 

相关文章:

[C/C++]指针详讲-让你不在害怕指针

个人主页&#xff1a;北海 &#x1f390;CSDN新晋作者 &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏✨收录专栏&#xff1a;C/C&#x1f91d;希望作者的文章能对你有所帮助&#xff0c;有不足的地方请在评论区留言指正&#xff0c;大家一起学习交流&#xff01;&#x1f9…...

无涯教程-Android - Frame Layout函数

Frame Layout 旨在遮挡屏幕上的某个区域以显示单个项目&#xff0c;通常&#xff0c;应使用FrameLayout来保存单个子视图&#xff0c;因为在子视图彼此不重叠的情况下&#xff0c;难以以可扩展到不同屏幕尺寸的方式组织子视图。 不过&#xff0c;您可以使用android:layout_grav…...

docker desktop安装es 并连接elasticsearch-head:5

首先要保证docker安装成功&#xff0c;打开cmd&#xff0c;输入docker -v&#xff0c;出现如下界面说明安装成功了 下面开始安装es 第一步&#xff1a;拉取es镜像 docker pull elasticsearch:7.6.2第二步&#xff1a;运行容器 docker run -d --namees7 --restartalways -p 9…...

计网(第四章)(网络层)(六)

目录 一、路由选择协议&#xff08;动态路由自动获取路由信息&#xff09;概述&#xff1a; 二、因特网采用的路由协议 主要特点&#xff1a; 1.自适应 2.分布式 3.分层次 因特网采用分层次的路由选择协议&#xff1a; 三、常见的路由选择协议 一、路由选择协议&#xff…...

科研无人机平台P600进阶版,突破科研难题!

随着无人机技术日益成熟&#xff0c;无人机的应用领域不断扩大&#xff0c;对无人机研发的需求也在不断增加。然而&#xff0c;许多开发人员面临着无法从零开始构建无人机的时间和精力压力&#xff0c;同时也缺乏适合的软件平台来支持他们的开发工作。为了解决这个问题&#xf…...

Apache的简单介绍(LAMP架构+搭建Discuz论坛)

文章目录 1.Apache概述1.1什么是apache1.2 apache的功能及特性1.2.1功能1.2.2特性 1.3 MPM 工作模式1.3.1 prefork模式1.3.2 worker模式1.3.3 event模式 2.LAMP概述2.1 LAMP的组成2.2 LAMP各组件的主要作用2.3 LAMP的工作过程2.4CGI和FastCGI 3.搭建Discuz论坛所需4.编译安装Ap…...

CDL基础原理

一、CDL简介 CDL&#xff08;全称Change Data Loader&#xff09;是一个基于Kafka Connect框架的实时数据集成服务。 CDL服务能够从各种OLTP数据库中捕获数据库的Data Change事件&#xff0c;并推送到kafka&#xff0c;再由sink connector推送到大数据生态系统中。 CDL目前支…...

WPF基础入门-Class7-WPF-MVVN框架

WPF基础入门 Class7-MVVN框架 使用框架可以省掉如Class6中的ViewModelBase.cs的OnPropertyChanged&#xff0c;亦方便命令传参 1、NuGet安装CommunityToolkit.Mvvm&#xff08;原Mircrosoft.Toolkit.Mvvm&#xff09;也可以安装MVVMLight等其他集成库 2、显示页面&#xff1…...

C语言练习题第三弹!!!绝对典中典!!!

目录 1.单身狗1 1.1 题目 1.2 分析推理 1.3 代码实现 2.单身狗2 2.1 题目 2.2 分析推理 2.3 代码实现 3.字符串左旋 3.1 题目 3.2 分析推理 3.3 代码实现 3.3.1 方法一 3.3.2 优化一 3.3.2.1 思路分析 3.3.2.2 strcpy函数和strncat函数 3.3.2.3 代码实现 3.3.…...

Jedis

Jedis 使用Java操作redis Jedis是redis官方推荐的Java连接开发工具&#xff01; 使用Java操作redis的中间件 测试 导入对应的依赖 <!-- https://mvnrepository.com/artifact/redis.clients/jedis --><dependency><groupId>redis.clients</groupId&g…...

Linux 使用TCP_INFO查询TCP连接的状态信息

Linux 上可以使用TCP_INFO查询TCP连接状态信息包括&#xff1a; 发送方拥塞窗口阈值、发送方缓冲区拥塞窗口、advmss&#xff08;Advertised MSS&#xff09;、通过 ACK 确认的累计字节数等等 struct tcp_info {__u8 tcpi_state;__u8 tcpi_ca_state;__u8 tcpi_retransmits;__…...

软件测试案例 | 气象探测库存管理系统的集成测试计划

将经过单元测试的模块按照设计要求连接起来&#xff0c;组成规定的软件系统的过程被称为“集成”。集成测试也被称为组装测试、联合测试、子系统测试或部件测试等&#xff0c;其主要用于检查各个软件单元之间的接口是否正确。集成测试同时也是单元测试的逻辑扩展&#xff0c;即…...

vue点击按钮重新加载页面(vue第一次加载页面点击按钮出现页面刷新问题之后一切正常)

问题描述 所开发的vue项目每次跑起来之后就会出现点击按钮后重新加载整个页面的问题&#xff0c;但是只会在第一次点击的时候出现&#xff0c;后面就不会在出现加载整个页面的情况。 原因 在form表单中使用button按钮导致form表单进行了页面刷新。button默认的“type‘submi…...

软件工程(十一) 系统设计分类

我们知道需求规格说明书(SRS)落地之后, 就要开始着手系统设计了,看一下这个系统该如何来设计,并且如何实现。学习系统设计之前,需要先了解系统设计有哪些分类。 系统设计的分类如下 界面设计结构化设计面向对象设计(最重要)1、界面设计 界面设计也叫做人机界面设计,属于…...

数字转中文大写金额

有时候&#xff0c;我们需要显示中文大写金额&#xff0c;比如打印银行付款申请单等。 新建一个工程&#xff0c;加入一个标准模块在模块中加入如下代码&#xff0c;窗口中调用 AmountInChineseWords 函数即可。最大解析到百万亿&#xff0c;小数最多解析两位到分。 模块代码…...

Java——HashMap和HashTable的区别

Java——HashMap和HashTable的区别 Java HashMap和HashTable的区别1. 继承的父类2. 线程安全性3. null值问题4. 初始容量及扩容方式5. 遍历方式6. 计算hash值方式 Java HashMap和HashTable的区别 1. 继承的父类 都实现了Map、Cloneable&#xff08;可复制&#xff09;、Seria…...

Docker去除sudo权限

Docker去除sudo权限 使用docker命令时&#xff0c;每次都要sudo提权&#xff0c;否则就会报错提示无权限。 1.查看docker用户组及成员 sudo cat /etc/group | grep docker2.添加docker用户组 sudo groupadd docker3.添加用户到docker组 sudo gpasswd -a ${USER} docker4.增…...

【ROS系统】Ubuntu22.04系统中安装ROS2系统_ubuntu 安装ros2_GoesM

【ROS系统】Ubuntu22.04系统中安装ROS2系统_ubuntu 安装ros2_GoesM Excerpt ROS仿真、专为自动驾驶研发提供的系统平台_ubuntu 安装ros2 参考博客&#xff1a;ROS 安装详细教程 —— Ubuntu22.0.4 LTS 安装 Part 0. 准备 首先&#xff0c;我们需要一个Ubuntu系统。 Part 1. …...

MySQL8.0.22安装过程记录(个人笔记)

1.点击下载MySQL 2.解压到本地磁盘&#xff08;注意路径中不要有中文&#xff09; 3.在解压目录创建my.ini文件 文件内容为 [mysql] # 设置mysql客户端默认字符集 default-character-setutf8[mysqld] # 设置端口 port 3306 # 设计mysql的安装路径 basedirE:\01.app\05.Tool…...

Python中pip和conda的爱恨情仇

在使用pip和conda时&#xff0c;是否也有过以下的疑惑&#xff1f;&#xff1f;&#xff1f; 目前只总结了以下常见的几种混淆&#xff0c;如有学者还有其它疑惑&#xff0c;欢迎留言讨论&#xff0c;我会解答更新&#xff0c;帮助自己理清的同时&#xff0c;也帮助其他同样困…...

HTTPS协议原理

目录 前言 1.理解加密和解密 2.为什么要加密 3.常见的加密方式 3.1对称加密 3.2非对称加密 4.数据摘要和数据指纹 5. 数字签名 6.HTTPS的加密策略 6.1只使用对称加密 6.2使用非对称加密 6.2.1服务端使用非对称加密 6.2.2双方都使用非对称加密 6.3对称加密非对称加…...

C语言每日一练------Day(6)

本专栏为c语言练习专栏&#xff0c;适合刚刚学完c语言的初学者。本专栏每天会不定时更新&#xff0c;通过每天练习&#xff0c;进一步对c语言的重难点知识进行更深入的学习。 今日练习题关键字&#xff1a;整数转换 异或 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn…...

springboot中使用ElasticSearch

引入依赖 修改我们的pom.xml&#xff0c;加入spring-boot-starter-data-elasticsearch <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency>编写配…...

十二、集合(2)

本章概要 添加元素组集合的打印列表 List 添加元素组 在 java.util 包中的 Arrays 和 Collections 类中都有很多实用的方法&#xff0c;可以在一个 Collection 中添加一组元素。 Arrays.asList() 方法接受一个数组或是逗号分隔的元素列表&#xff08;使用可变参数&#xff…...

【网络设备】交换机的概念、工作原理、功能以及以太网帧格式

个人主页&#xff1a;insist--个人主页​​​​​​ 本文专栏&#xff1a;网络基础——带你走进网络世界 本专栏会持续更新网络基础知识&#xff0c;希望大家多多支持&#xff0c;让我们一起探索这个神奇而广阔的网络世界。 目录 一、认识交换机 二、交换机的主要功能 1、数…...

研磨设计模式day11观察者模式

目录 场景 代码示例 定义 观察者模式的优缺点 本质 何时选用 简单变型-区别对待观察者 场景 我是一家报社&#xff0c;每当我发布一个新的报纸时&#xff0c;所有订阅我家报社的读者都可以接收到 代码示例 报纸对象 package day11观察者模式;import java.util.Observ…...

第八周第二天学习总结 | MySQL入门及练习学习第四天

实操练习&#xff1a; 1.建立一个员工表和与之对应的部门表 2.建立外键约束 3.使用多表查询&#xff0c;直接查询部门表和员工表 发现&#xff1a;有很多多余的因笛卡尔乘积而带来的多余输出内容 我想要的到简单明了的数据结果&#xff0c;要消除多于因笛卡尔乘积带来的输出…...

WPF数据转换

在基本绑定中&#xff0c;信息从源到目标的传递过程中没有任何变化。这看起来是符合逻辑的&#xff0c;但我们并不总是希望出现这种行为。通常&#xff0c;数据源使用的是低级表达方式&#xff0c;我们可能不希望直接在用户界面使用这种低级表达方式。WPF提供了两个工具&#x…...

《Go 语言第一课》课程学习笔记(十三)

方法 认识 Go 方法 Go 语言从设计伊始&#xff0c;就不支持经典的面向对象语法元素&#xff0c;比如类、对象、继承&#xff0c;等等&#xff0c;但 Go 语言仍保留了名为“方法&#xff08;method&#xff09;”的语法元素。当然&#xff0c;Go 语言中的方法和面向对象中的方…...

基于RUM高效治理网站用户体验入门-价值篇

用户体验 用户体验基本包含访问网站的性能、可用性和正确性。通俗的讲&#xff0c;就是一把通过用户访问测量【设计者】意图的尺子。 本文目的 网站如何传递出设计者的意图&#xff0c;可能页面加载时间太长、或者页面在用户的浏览器中渲染时间太慢&#xff0c;或者第三方设备…...

Unity之Photon PUN2开发多人游戏如何实现组队功能

前言 Photon Unity Networking 2 (PUN2) 是一款基于Photon Cloud的Unity多人游戏开发框架。它提供了一系列易于使用的API和工具,使开发者可以快速构建多人戏,并轻松处理多人游戏中的网络同步、房间管理、玩家匹配等问题。 我们在查看Pun2的Demo时,会发现Demo中自带了一个简…...

大数据Flink简介与架构剖析并搭建基础运行环境

文章目录 前言Flink 简介Flink 集群剖析Flink应用场景Flink基础运行环境搭建Docker安装docker-compose文件编写创建并运行容器访问Flink web界面 前言 前面我们分别介绍了大数据计算框架Hadoop与Spark,虽然他们有的有着良好的分布式文件系统和分布式计算引擎&#xff0c;有的有…...

RISC-V IOPMP实际用例-Rapid-k模型在NVIDIA上的应用

安全之安全(security)博客目录导读 2023 RISC-V中国峰会 安全相关议题汇总 说明&#xff1a;本文参考RISC-V 2023中国峰会如下议题&#xff0c;版权归原作者所有。...

【UE5】给模型指定面添加自定义材质

实现步骤 1. 首先我们向UE中导入一个简单的模型&#xff0c;可以看到目前该模型的材质插槽只有一个&#xff0c;当我们修改材质时会使得模型整体的材质全部改变&#xff0c;如果我们只想改变模型的某些面的材质就需要继续做后续操作。 2. 选择建模模式 3. 在模式工具栏中点击…...

mall:redis项目源码解析

文章目录 一、mall开源项目1.1 来源1.2 项目转移1.3 项目克隆 二、Redis 非关系型数据库2.1 Redis简介2.2 分布式后端项目的使用流程2.3 分布式后端项目的使用场景2.4 常见的缓存问题 三、源码解析3.1 集成与配置3.1.1 导入依赖3.1.2 添加配置3.1.3 全局跨域配置 3.2 Redis测试…...

RISC-V Linux系统kernel制作

文章目录 1、下载2、编译 1、下载 Linux 官网地址:https://www.kernel.org $ wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.10.181.tar.xz $ tar xvf linux-5.10.181.tar.xz $ cd linux-5.10.1812、编译 安装依赖 $ sudo apt-get install -y flex bison bui…...

5G NR:PRACH时域资源

PRACH occasion时域位置由高层参数RACH-ConfigGeneric->prach-ConfigurationIndex指示&#xff0c;根据小区不同的频域和模式&#xff0c;38.211的第6.3.3节中给出了prach-ConfigurationIndex所对应的表格。 小区频段为FR1&#xff0c;FDD模式(paired频谱)/SUL&#xff0c;…...

LLaMA-2的模型架构

输入token&#xff1b;[B, L] 输出probs:[B, L, vab_size]...

掌握Java框架之Struts,开启高效开发之旅!

当今的软件开发世界&#xff0c;Java框架如Struts已经成为构建企业级应用的重要工具。Struts作为一个流行的MVC框架&#xff0c;不仅简化了Java Web开发&#xff0c;还提高了软件的可维护性和可扩展性。本文将带你走进Struts的世界&#xff0c;探索其魅力所在&#xff0c;让你领…...

关于Vue.set()

简介 Vue.set() 是 Vue 中的一个全局方法&#xff0c;其主要作用是向响应式对象添加新的属性&#xff0c;并确保新属性同样具有响应式。在 Vue.js 中&#xff0c;当数据对象的属性被直接修改时&#xff0c;Vue 可以监测到数据变化并响应变化。但若添加新的响应式对象属性时&am…...

Selenium 遇见伪元素该如何处理?

问题发生 在很多前端页面中&#xff0c;大家会见到很多&#xff1a;:before、::after 元素&#xff0c;比如【百度流量研究院】&#xff1a; 比如【百度疫情大数据平台】&#xff1a; 以【百度疫情大数据平台】为例&#xff0c;“累计确诊”文本并没有显示在 HTML 源代码中&am…...

RPA技术介绍与应用价值

一、什么是RPA技术? RPA(Robotic Process Automation)机器人流程自动化,是一种能够模拟人类来执行重复性任务的新型技术。RPA可实现统筹安排、自动化业务处理,并提升业务工作流处理效率。用户只需通过图形方式显示的计算机操作界面对RPA软件进行动态设定即可。借助RPA (R…...

产品经理,需要具备哪些能力和知识

作为产品经理&#xff0c;需要具备以下能力和知识&#xff1a; 产品管理能力&#xff1a;具备全面的产品管理能力&#xff0c;包括产品策划、需求分析、产品规划、产品设计、项目管理、市场调研和竞争分析等。 用户导向思维&#xff1a;能够理解用户需求和期望&#xff0c;以…...

【C++】map和set

map和set 文章目录 map和set关联式容器setset介绍set的函数测试代码 multiset注意事项测试代码 mapmap介绍map的函数测试代码 关联式容器 前面了解过的vector&#xff0c;list&#xff0c;string等容器都是序列式容器&#xff0c;存储的都是元素本身&#xff0c;底层都是线性的…...

crawlab通过docker单节点部署简单爬虫

crawlab 单节点docker安装 此处介绍的是单节点的方式&#xff0c;多节点的情况可以把爬虫上传到一个节点中&#xff0c;之后会同步到其它节点上 version: 3.3 services:master:image: crawlabteam/crawlabcontainer_name: crawlab_masterrestart: alwaysenvironment:CRAWLAB…...

【STM32】中断与NVIC以外部中断为例

前言 在stm32中姑且可以认为&#xff0c;异常就是中断 单片机上电之后&#xff0c;首先执行启动文件&#xff0c;开辟堆栈之后&#xff0c;开始初始化中断向量表。 NVIC NVIC NVIC是嵌套向量中断控制器&#xff0c;控制着整个芯片中断相关的功能&#xff0c;它跟内核紧密耦…...

大学生网页设计制作作业实例代码 (全网最全,建议收藏) HTML+CSS+JS

文章目录 &#x1f4da;web前端期末大作业 (1500套) 集合一、网页介绍二、网页集合 三、作品演示A电影主题B漫画主题C商城主题D家乡主题E旅游主题F餐饮/美食主题G环境主题H游戏主题I 个人主题K体育主题L博客主题M汽车主题N文化主题P美妆主题Q企业主题R教育主题S其他主题 &#…...

Llama模型结构解析(源码阅读)

目录 1. LlamaModel整体结构流程图2. LlamaRMSNorm3. LlamaMLP4. LlamaRotaryEmbedding 参考资料&#xff1a; https://zhuanlan.zhihu.com/p/636784644 https://spaces.ac.cn/archives/8265 ——《Transformer升级之路&#xff1a;2、博采众长的旋转式位置编码》 前言&#x…...

基于XML实现SpringIoC配置

目录 SpringIoc创建与使用的大致步骤 一.基于xml配置SpringIoc 二.基于xml配置DI 三.创建IoC容器并获取组件 SpringIoc创建与使用的大致步骤 SpringIoC的创建与使用过程分为3步 1.编写配置信息&#xff08;编写XML&#xff0c;注解、Java类&#xff09; 2.创建IoC容器&…...

Kaniko在containerd中无特权快速构建并推送容器镜像

目录 一、kaniko是什么 二、kaniko工作原理 三、kanijo工作在Containerd上 基于serverless的考虑&#xff0c;我们选择了kaniko作为镜像打包工具&#xff0c;它是google提供了一种不需要特权就可以构建的docker镜像构建工具。 一、kaniko是什么 kaniko 是一种在容器或 Kube…...