C语言-指针变量和变量指针
指针
预备知识
内存地址
-
字节:字节是内存的容量单位,英文名Byte,1Byte=8bits
-
地址:系统为了便于区分每一个字节面对它们的逐一进行编号(编号是唯一的),称为内存地址,简称地址。int a=5;
基地址(首地址)
-
单字节数据:对于单字节数据而言,其地址就是其字节编号。举例:char a='A'
-
多字节数据:对于多字节数据而言,其地址是所有字节中编号最小的那个,称为基地址()
取地址符
-
每个变量都是一块的内存,都可以通过取址符
&
获取其地址。 -
例如:
int a=100;printf("整型变量a的地址是:%p\n",&a);//64位系统,是12位16进制int c='x';printf("字符变量c的地址是:%c");
-
主语:
-
虽然不同的变量的尺寸是不同的,但是它们的地址尺寸是一致的。
-
不同的地址虽然形式上看起来是一样的,但由于它们代表的内存尺寸和类型都不同,因此它们在逻辑上严格区分的。
-
为什么要引入指针
-
为函数修改实参提供支持。
-
为动态内存管理提供支持。
-
为动态的的数据结构(链表、队列等)提供支持
-
为内存访问提拱了另一种途径。
变量指针与指针变量
指针概念
内存单元与地址机制
-
内存单元划分
-
系统将内存划分为连续的基本存储单元,每个单元的容量为1字节(8bits)
-
每个内存单元拥有唯一编号。称为内存地址(十六进制表示:)
-
-
变量存储特性
-
变量根据数据类型占据不同数量的内存单元:
-
char
类型占1个字节(1个单元) -
int
类型占4个字节(4个单元) -
double
类型占8个字节(8个单元)
-
-
变量的基地址(首地址)是其首个内存单元的地址(首地址一般是这个一组编号中最小的那个)
-
变量指针与指针变量
对比维度 | 变量指针 | 指针变量 |
---|---|---|
本质 | 内存地址(首地址\基地址) 变量指针其实就是变量的首地址 | 存储地址的普通变量 |
操作符 | & (取地址符) | * (声明符,解引用符,如:int *p ) |
代码示例 | &a (获取变量a地址) | int* p =&a |
核心特性 | 不可修改(地址由系统分配) | 可修改指向(p=&b ) |
指向:
指针变量中存放 谁 的地址,就说明该指针变量指向了 谁
指针的尺寸
系统类型 | 指针尺寸 | 地址位数 | 十六进制显示长度 |
---|---|---|---|
32位系统 | 4字节(int) | 32bit | 8位(如0x0804A000) |
64位系统 | 8字节(long) | 48bit | 12位(如0x7FFDEADBEEF) |
指针的本质
-
变量指针:数据的门牌号(&a)
-
指针变量:存储门牌号的笔记本(int *p)
-
指向操作:通过门牌号访问数据(*p)
int a=10;printf("%d\n",a);//访问a的值int *p=&a;printf("%d\n",*p);//访问p指向a的值,其实就是访问a的值
小贴士:
Linux系统中打印地址时,最多显示12个十六进制数,为什么? Linux64位操作系统中,一个内存地址占8个字节,一个字节8bit位,所以一个地址88=64bit位,每4个bit可以表示1个十六进制数; 64个bit位用十六进制表示最多有16个数值位; 系统为了寻址方便,默认当前计算机系统没必要寻址64bit为,只寻址了48个bit为,所以用12个十六进制数表示一个地址 二进制: 01001010 十六进制:0x4A 416+10=74 注意: 在Linux64位操作系统中,指针类型的变量占8个字节的内存空间 在Linux32位操作系统中,指针类型的变量占4个字节的内存空间
内存数据的存取方式
在c语言中对内存数据(变量、数组元素等)的存取有两种方式:
直接存取
-
通过基本类型(整型、浮点型、字符型)的变量,访问这个变量代表内存空间的数据
-
通过数组元素的引用,访问这个引用代表的内存空间数据
//基本类型变量int a=10;//存printf("%d\n",a);//取//数组元素int arr[]={11,12,13};//存arr[0]=66;//存printf("%d\n",arr[0]);//取
间接存取
-
通过指针变量,间接访问内存中的数据
-
解引用符
*
:读作声明符或者解引用符。如果*
前面有数据类型,读作声明指针;如果*
前面没有数据类型,读作解引用。案例
#include <stdio.h>int main(int argc,char *argv[]){// 定义一个普通变量int a = 3;// 定义一个指针变量,并赋值int* p = &a; // *p前面的数据类型是用来修饰 = 后面的 a的类型// 访问变量a,直接访问printf("直接访问-%d\n",a);// 访问变量a,通过指针变量p访问,间接访问printf("间接访问-%d\n",*p);// *p 叫做解引用// 访问指针变量p的值,也就是访问变量a的地址 %p 输出 变量的地址printf("地址访问-%p,%p,%p\n",p,&p,&a);return 0;}
变量指针与指针变量
指针变量的定义
语法:
数据类型 *变量列表
举例:
int a;//普通变量,拥有真实的数据存放空间int *a_,*b_;//指针变量,无法存放数据,只能存储其他变量的地址
注意:指针变量的值只能是8、12位的十六进制整数
注意:
①虽然定义指针变量
*a
,是在变量名前加上*
,但是实际变量名依然为a
,而不是*a
②使用指针变量间接访问内存数据时,指针变量必须要明确的指向。(指向:指针变量存放谁的地址,就指向谁)
③如果想要借助指针变量间接访问指针变量保存的内存地址上的数据,可以使用指针变量前加
*
,来间接返回访问。指针变量前加*
,如果不带数据类型,就称之为对指针变量解引用int i=5,*p;p=&i;//将i的地址赋值给指针变量p;printf("%lx,%p,%p\n",p,p,&p); %p-&p(p自己的地址) %p- p(i对应的地址)printf("%d\n",*p);解引用所储存变量空间的地址*p=10;//间接给p对应的地址上的数据空间赋值,也就是给变量i赋值printf("%d,%d\n",*p,i);//10 10
④指针变量只能指向同类型的变量,借助指针变量访问内存,一次访问内存
大小是取决于指针变量的类型
int a=10;int *p=&a;//*p前面的类型是p指向变量a的类型,这个类型要么完全一致,要么可以转换
⑤指针变量在定义时可以初始化,这一点和普通变量是一样的。
int a=5;int *p=&a;//定义指针变量的同时初始化printf("%d\n",*p);int b;int *p1=&b; //指针初始化的时候,不需要关注指向变量空间中是否有值printf("%d\n",*p1); 会出错
指针变量的使用
使用
-
指针变量的赋值
//方式1int a, *p;p=&a;// 先定义,后赋值//方式2int a1,*p1,*q1=&al; //定义并初始化p1=ql;//其实就是变量赋值,指针变量q1的值赋值给p1,此时q1和p1同时指向a1
-
操作指针变量的值
int a,*p,*q=&a;p=q;//将指针变量q的值赋值给指针变量p,此时p和q都指向了变量aprintf("%p",p);//访问的是指针变量p的值(也就是变量a的地址)printf("%p",q);
-
操作指针变量指向的值
int a=6;*q=&a,b=25;//一定要注意指针变量q的变量名就是q*q=10;//访问q指向的变量a的空间,其实就是间接的给a赋值(a=10)printf("%d,%d\n",*q,a);//10 10q=&b;//一个指针变量只能同一时刻指向一个变量,但是一个变量可以同时被多个指针变量指向printf("%d,%d\n",*q,a);// 25 10
两个指针运算符使用
-
&
取地址运算符。&a是变量a的地址。这个是变量指针 -
*
指针运算符、解引用符、间接访问运算符,*p是指针变量p指向的对象值。这个是指针变量。
案例
案例1
-
需求:通过指针变量访问整型变量
-
分析:
-
代码:
#include <stdio.h>void main(){int a=3,b=4,*p1=&a,*p2=&b;printf("a=%d,b=%d\n",*p1,*p2);}
案例2
-
需求:声明a,b两个变量,使用间接存取的方式实现数据交换。
-
分析:
-
代码:
#include <stdio.h>int main(){int a=3,b=4,*p_a=&a,*p_b=&b,*p_t;printf("交换前为%d,%d\n",*p_a,*P_b);//3,4//交换位置p_t=p_a;P_a=P_b;p_b=p_t;printf("交换后为%d,%d,%d,%d\n",*p_a,*P_b);}
总结:此时改变的只是指针的指向,原始变量a,b中数据并没有发生改变
-
代码:数据改变,不推荐
#include <stdio.h>int main(){int a=3,b=4,*p_a=&a,*p_b=&b,temp;printf("交换前为%d,%d\n",*p_a,*P_b);//3,4//交换位置temp=*p_a;*P_a=*P_b;*p_b=temp;printf("交换后为%d,%d\n",*p_a,*P_b);}
总结:此时改变的只是指针的指向,原始变量a,b中数据发生改变
案例3
-
需求:输入a、b两个整数,按先大后小的顺序输出a和b
-
分析:
-
代码:指向改变
#include <stdio.h>int main(){int a=3,b=4,*p_a=&a,*p_b=&b,*p_t;if(a<b){p_t=p_a;P_a=P_b;p_b=p_t;}//交换位置printf("按从小到大的顺序输出a,b的值%d>%d\n",*p_a,*P_b);}
-
代码:
#include <stdio.h>int main(){int a=3,b=4,*p_a=&a,*p_b=&b,temp;printf("交换前为%d,%d\n",*p_a,*P_b);//3,4if(a<b){//交换位置temp=*p_a;*P_a=*P_b;*p_b=temp;}printf("按从小到大的顺序输出a,b的值%d>%d\n",*p_a,*P_b);}
指针变量做函数参数
指针变量做函数参数往往传递的是变量的地址(基地址),借助与指针变量间接访问是可以修改实参变量数据的。
案例:
-
需求:有a,b两个变量,要求交换后输出(要求函数处理,用指针变量做函数的参数)
-
方式1:交换指向(指针指向发生改变,指针指向的对象的值不变)
#include <stdio.h>//定义一个函数,实现两个数的交换void swap(int *p_a,int *p_b){int *p_t;//以下写法只会改变指针指向 不会改变指向对象的值p_t=p_a;P_a=P_b;p_b=p_t;printf("%d,%d\n",*P_a,*p_b);}int main(){int a=3,b=5,*p_a=&a,*p_b=&b,*p_t;swap(&a,&b);printf("a=%d,b=%d\n",a,b)return 0;}
-
方式2:交换数据(指针指向不改变,指针指向对象的值发生变化)
#include <stdio.h>void swap(int *p_a,int *p_b){int temp;//以下写法只会改变指针指向 不会改变指向对象的值temp=*p_a;*P_a=*P_b;*p_b=temp;printf("%d,%d\n",*P_a,*p_b);}int main(){int a=3,b=4,*p_a=&a,*p_b=&b,temp;swap(&a,&b);printf("a=%d,b=%d\n",a,b);}
指针变量指向数组元素
数组元素指针
-
数组的指针就是数组中的第一个元素的地址,也就是数组的首地址
-
数组元素的指针是指数组的首地址。因此,同样可以用指针变量来指向数组或数组元素。
-
在C语言中,由于数组名代表数组的首地址,因此,数组名实际上也是指针,访问数组名就是访问数组首地址
#include <stdio.h>//定义一个函数,实现两个数的交换int main(){int arr[]={11,12,13};int *p1=arr[0];int *p2=arr;printf("%p,%p,%p\n",p1,p2,arr);return 0;}
注意:虽然我们定义一个指针变量接收了数组地址,但不能理解为指针变量指向了数组。而应该理解为指向了数组的元素(默认为第1个元素)。
指针运算
指针运算:前提是指针变量必须要指向数组的某个元素。(指针运算只能发生在同一数组)
序号 指针运算 说明 1 自增:p++、++p、p=p+1、p+=1 指向下一个元素的地址 2 自减:p--、--p、p-=1 指向下一个元素的地址 3 加n个数:p+n(n*sizeof(type)) 后n个元素的(首)地址 4 减n个数:p-n 前n个元素的(首地址) 5 指针相减:p1-p2 p1,p2之间相差几个元素 6 指针比较:p1<p2 前面的指针小于后面的指针 说明: ①如果指针变量p已指向数组中的一个元素,则p+1指向同一数组中的下一个元素,p-1指向同一数组中的上一个元素。即p+1或p-1也表示地址。但要注意的是,虽然指针变量p中存放的是地址,但p+1并不表示该地址加1,而表示在原地址的基础上加了该数据类型所占的字节数d(d=sizeof(数据类型))。 ②如果p原来指向a[0],执行++p后p的值改变了,在p的原值基础上加d,这样p就指向数组的下一个元素a[1]。d是数组元素占的字节数。 ③如果p的初值为&a[0]则p+i和a+i就是数组元素a[i]的地址,或者说,它们指向a数组的第i个元素。 ④
*(p+i)
或(a+i)是p+i或a+i所指向的数组元素,即a[i]。 ⑤如果指针变量p1和p2都指向同一数组,如执行p2-p1,结果是两个地址之差除以数组元素的长度d。#include <stdio.h>int main(){int arr[]={11,22,33,44,55};int *p1=arr+4;//55等价于arr[4]int *p2=arr+1;//22等价于arr[1]aiprintf("%ld\n",p1-p2);//3 4*4-1*4=12 12(相差的字节数)/4(每个元素的大小ai)=3(元素的大小)return 0;}
案例
案例1
-
需求:通过下标法和指针法遍历数组
-
代码:
#include <stdio.h>//下标法遍历数组void arr1(int arr[],int len){//通过循环遍历for(int i=0;i<len;i++){printf("%-3d",arr[i]);}printf("\n");}void arr2(int arr[],int len){int *p=arr;register int i=0;for(;i<len;i++){printf("%-3d",*p;p++;}printf("\n");}void arr3(int arr[],int len){int *p=arr;register int i=0;for(;i<len;i++){printf("%-3d",*(arr+i));}printf("\n");}int main(){int array[]={11,22,33,44,55};int len=sizeof(arr)/sizeof(arr[0]);arr1(array,len);arr2(array,len);arr3(array,len);return 0;}
#include <stdio.h>int arr2() {int arr1[] = {11, 22, 33, 44, 55, 66, 77, 88};int *p = arr1;// 1. 输出数组首元素 11printf("%d\n", *p); // 2. 指针后移,输出 22p++;printf("%d\n", *p); // 3. 先取值 22,指针再后移。此时 x=22,p 指向 33int x = *p++; printf("%d,%d\n", x, *p); // 输出 22,33// 4. 指针先前移到 44,取值 44。y=44,p 指向 44int y = *(++p); printf("%d,%d\n", y, *p); // 输出 44,44// 5. 对当前指向的元素(44)自增,变为 45(*p)++; printf("%d\n", *p); // 输出 45return 0;}int main(int argc, char *argv[]) {arr2();return 0;}
*p++ 先解引用p,然后p这个指针自增
int arr[]={11,22,33},*p=arr;int x=*p++;
(*p)++ 先解引用p,然后使用解引用出来的数据自增
int arr[]={11,22,33};*p=arr;int x=(*p)++;
通过指针引用数组元素
引用一个数组元素,可以用:
①下标法:如:
arr[i]
形式②指针法:如:
*(arr+i)
或者*(p+i)
,其中arr是数组名,p是指向数组元素的指针变量,其初始值;p=arr;案例:
需求:有一个整型数组arr,有十个元素,输出数组中的全部元素。
-
下标法:(通过改变下标输出所有元素)
#include <stdio.h>void main(){int arr[10];int i;// 给数组元素赋值for(i = 0; i < 10; i++)scanf("%d",&arr[i]);// 遍历数组元素for(i = 0; i < 10; i++)printf("%-4d%",*(arr + i));printf("\n"); }
-
指针法(地址):(通过数组名计算出数组元素地址,找出数组元素)
#include <stdio.h>void main(){int arr[10];int i;// 给数组元素赋值for(i = 0; i < 10; i++)scanf("%d",&arr[i]);// 遍历数组元素for(i = 0; i < 10; i++)printf("%-4d%",arr[i]);printf("\n"); }
-
指针法(指针变量):用指针变量指向数组元素
#include <stdio.h>void main(){int arr[10];int *p, i;// 给数组元素赋值for(i = 0; i < 10; i++)scanf("%d",&arr[i]);// 遍历数组元素for(p = arr; p < (arr + 10); p++)printf("%-4d%",*p);printf("\n"); }
注意:数组一旦创建,就无法改变其值
以上三种写法比较:
-
第种写法和第②种写法执行效率相同。系统是将arr[]转换为*(arr+i)处理的,即先计算出地址,因此比较费时。
-
第③种方法比①②种方法快。用指针变量直接指向数组元素,不必每次都重新计算地址。(p++)能大大提高执行效率。
-
用第①种写法比较直观,而用地址法或者指针变量的方法难以很快判断出当前处理的元素。
使用指针变量指向数组元素时(上面第③种写法),注意以下三点:
①
*(p--)相当于arr[i--],先*p,在p--
;*(p++)相当于arr[i++],先*p,在p++
②
*(++p)相当于arr[++i],先++p,在*
;*(--p)相当于arr[--i],先--p,在*
③
*p++先*p,在p++
④
(*p)++先*p,在*p++
*p++ (p++) (*p)++
具体关系参照下面表格
数组名做函数参数
表现形式:
①形参和实参都是数组名
void fun(int arr[],int len){......}void main(){int arr[]={11,22,33};fun(arr,sizeof(arr)/sizeof(arr[0]));}
②实参用数组名,形参用指针变量
void fun(int *p,int len){......}void main(){int arr[]={11,22,33};fun(p,sizeof(arr)/sizeof(arr[0]));}
③实参和形参都用指针变量
void fun(int *p,int len){......}void main(){int arr[]={11,22,33};int *p=arr;fun(p,sizeof(arr)/sizeof(arr[0]));}
④实参用指针,形参用数组名
void fun(int arr[],int len){......}void main(){int arr[]={11,22,33};int *p=arr;fun(p,sizeof(arr)/sizeof(arr[0]));}
案例:
需求:将数组a中n个元素
分析:
代码:
#include <stdio.h>/*** 数组的反转:数组实现*/ void inv(int arr[], int len){// 反转思路:将第0个和len -1个进行对调,将第1个和len-2个进行对调...// 定义循环变量和临时变量register int i = 0, temp;// 遍历数组for(; i < len/2; i++){// 交换temp = arr[i];arr[i] = arr[len - 1 - i];arr[len - 1 - i] = temp;}}/*** 数组的反转:指针实现*/ void inv2(int *p, int len){// 反转思路:将第0个和len -1个进行对调,将第1个和len-2个进行对调...// 定义循环变量和临时变量int *i = p, *j = p + len - 1, temp;// 遍历数组for(; i < j;i++,j--){// 交换temp = *i;*i = *j;*j = temp;}}/*** 遍历数组*/ void list(const int arr[],int len)for(int i = 0; i < len; i++) printf("%-3d",arr[i]);printf("\n");}int main(int argc,char *argv[]){int arr[] = {11,22,33,44,55,66};int len = sizeof(arr) / sizeof(arr[0]);list(arr,len);inv(arr,len);list(arr,len);inv2(arr,len);list(arr,len);return 0;}
-
相关文章:
C语言-指针变量和变量指针
指针 预备知识 内存地址 字节:字节是内存的容量单位,英文名Byte,1Byte8bits 地址:系统为了便于区分每一个字节面对它们的逐一进行编号(编号是唯一的),称为内存地址,简称地址。int…...
CMS漏洞-WordPress篇
一.姿势一:后台修改模板拿WebShell 1.使用以下命令开启docker cd /www/wwwroot / vulhub / wordpress / pwnscriptum docker - compose up - d 如果发现不能开启,可以检查版本和端口 2.访问网址登录成功后 外观 👉编辑 👉404.…...
初识Brainstorm(matlab)
Brainstorm是一款开源应用程序,专门用于分析脑部记录数据:MEG、EEG、fNIRS、ECoG、深部电极等。该应用程序免费,而且不需要Matlab许可证。Brainstorm主要优势是简单直观的图形界面,不需要任何编程知识。具体内容,可查看…...
2025年智能系统、自动化与控制国际学术会议(ISAC 2025)
重要信息 2025 International Conference on Intelligent Systems, Automation and Control 2025年3月28-30日 | 中国西安理工大学 | 会议官网: www.icisac.org 简介 在国家大力推动高质量发展与创新驱动战略的背景下,智能制造与自动化控制行业正迎…...
GGUF、Transformer、AWQ 详解与关系梳理
GGUF、Transformer、AWQ 详解与关系梳理 一、核心概念解析 Transformer 定义 :2017 年 Google 提出的基于自注意力机制的神经网络架构,是大语言模型的通用基础架构。功能 :用于文本生成、翻译、问答等任务,如 BERT、GPT 系列、…...
学习笔记|arduino uno r3|DS1307时钟芯片|Atmega328P| 设置时间|读取时间|无源晶振:DS1307时钟芯片实验
目录 芯片pinout: 实验器件: 实验连线 解决AVR 架构不支持 printf() 方法 使用GetTimeAndDate.ino设置时间: 使用SetTimeAndDate.ino设置时间: 芯片pinout: DS1307 是美国 DALLAS 公司推出的 I 总线接口实时时钟芯…...
Linux--进程创建
进程创建 写时拷贝(时间换空间) 更新页表项权限为只读----子进程写入----触发系统错误系统缺页中断,系统开始检测,系统判断写入区域是数据区还是代码区,如果是代码区就终结进程,如果是数据区就进行写时拷贝…...
MySQL 创建用户,建库,建表
以下是在 MySQL 中创建用户、数据库、表的详细操作步骤: 一、登录 MySQL -- 使用 root 用户登录(需替换为实际密码) mysql -u root -p输入密码后回车,进入 MySQL 命令行界面。 二、创建数据库 -- 创建名为 test_db 的数据库&a…...
成都国际数字影像产业园,文创产业运营新典范深度解析
成都国际数字影像产业园位于成都市蓉北商圈金牛片区福堤路99号,是金牛区政府与树莓集团携手打造的省级“文化科技”融合示范园区。该产业园已成为西南地区乃至全国数字影像产业的一颗璀璨明珠,其成功运营模式堪称文创产业运营的新典范。 产业定位与资源…...
33、如果 std::vector 的元素是指针,需要注意什么?
对 std::vector 元素为指针的情况,需要注意以下几点: 内存管理: 如果 std::vector 存储的是原始指针,那么仅仅清空 vector 或者让 vector 被销毁,并不会释放指针所指向的内存。因此,需要确保在 vector 被销…...
Docker 速通(总结)
Docker 命令 镜像 docker build: 从 Dockerfile 构建镜像。docker pull: 从 Docker Hub 或其他注册表拉取镜像。docker push: 将镜像推送到 Docker Hub 或其他注册表。docker images: 列出本地镜像。docker rmi: 删除本地镜像。 容器 docker run: 创建并启动一个新的容器。…...
算法训练篇06--力扣611.有效三角形的个数
目录 1.题目链接:611.有效三角形的个数 2.题目描述: 3.解法一:(暴力解法)(会超时): 4.解法二(排序双指针) 1.题目链接:611.有效三角形的个数 2.题目描述: 给定一个包含非负整数的数组 nums …...
Gin框架学习
一.介绍 Gin是一个用Go语言编写的web框架。它是一个类似于martini但拥有更好性能的API框架, 由于使用了httprouter,速度提高了近40倍。 如果你是性能和高效的追求者, 你会爱上Gin。 下载 go get -u github.com/gin-gonic/gin 二.Gin示例 学习的时候,写在…...
青少年编程与数学 02-011 MySQL数据库应用 07课题、表的操作
青少年编程与数学 02-011 MySQL数据库应用 07课题、表的操作 一、数据库表(Table)二、创建表语法格式示例注意事项 三、字段的命名规则基本规则命名规范建议示例 四、字段数据类型数值类型字符串类型日期和时间类型其他类型 五、选择合适的数据类型1. **…...
【详细解决】pycharm 终端出现报错:“Failed : 无法将“Failed”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。
昨天在终端一顿操作后突然打开pycharm时就开始报错: 无法将“Failed”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。 所在位置 行:1 字符: 1 Failed to act…...
AcWing 839:模拟堆 ← multiset + unordered_map
【题目来源】 https://www.acwing.com/problem/content/841/ 【题目描述】 维护一个集合,初始时集合为空,支持如下几种操作: 1. I x,插入一个数 x; 2. PM,输出当前集合中的最小值; 3. DM&#…...
cmake教程
CMake 是一个跨平台的自动化构建系统,广泛用于管理软件构建过程。它使用 CMakeLists.txt 文件来配置项目的构建过程,并生成适用于不同编译器和操作系统的构建文件(如 Makefile、Visual Studio 项目文件等)。以下是一个简单的 CMak…...
小蓝的括号串1(栈,蓝桥云课)
问题描述 小蓝有一个长度为 nn 的括号串,括号串仅由字符 ( 、 ) 构成,请你帮他判断一下该括号串是否合法,合法请输出 Yes ,反之输出 No 。 合法括号序列: 空串是合法括号序列。 若 ss 是合法括号序列,则 (…...
软考系统架构设计师考试学习和考试的知识点大纲,覆盖所有考试考点
以下是软考系统架构设计师考试的知识点大纲,覆盖所有官方考点,分为基础知识、核心技术、系统设计、案例分析、论文写作五大模块,帮助系统性学习和备考: 一、基础知识模块 计算机组成与体系结构 计算机硬件组成(CPU、内…...
车载以太网网络测试-18【传输层-DOIP协议-1】
目录 1 摘要2 DOIP协议的概述2.1 DOIP协议背景2.2 ISO 13400概述 3 DOIP报文的帧结构以及实例3.1 DOIP报文帧结构3.2 实例示例 总结 1 摘要 在汽车网络通信中,诊断扮演了非常重要的角色,无论是故障诊断、整车下线配置,还是ECU的软件更新、远…...
密码学(Public-Key Cryptography and Discrete Logarithms)
Public-Key Cryptography and Discrete Logarithms Discrete Logarithm 核心概念:离散对数是密码学中一个重要的数学问题,特别是在有限域和循环群中。它基于指数运算在某些群中是单向函数这一特性。也就是说,给定一个群 G G G和一个生成元 …...
自然语言处理|深入解析 PEGASUS:从原理到实践
一、引言 在信息爆炸的时代,互联网上的文本数据以极快的速度增长。无论是新闻资讯、学术论文、社交媒体动态,还是各类报告文档,我们每天接触到的文字信息量巨大。如何快速、准确地提取关键内容成为一项重要任务。文本摘要技术通过将长篇文本…...
矩阵指数的定义和基本性质
1. 矩阵指数的定义 矩阵指数 e A t e^{\boldsymbol{A}t} eAt 定义为幂级数的形式: e A t ∑ k 0 ∞ ( A t ) k k ! e^{\boldsymbol{A}t} \sum_{k0}^\infty \frac{(\boldsymbol{A}t)^k}{k!} eAtk0∑∞k!(At)k 当 A \boldsymbol{A} A 为 n n n \times n …...
react 技术栈请问该如何优化 DOM 大小
针对 React 应用中 DOM 大小过大 的问题,以下是详细的优化方案和具体操作步骤,帮助你提升 Lighthouse 性能评分和用户体验: 一、问题根源分析 DOM 大小过大(如超过 1500 个节点或深度超过 32 层)会导致: …...
redis,tar.gz安装后,接入systemctl报错解决
1. WARNING Memory overcommit must be enabled! 这种报错,有两种解决方法 1.1 修改系统参数 编辑 /etc/sysctl.conf 文件,设置 overcommit_memory 为 1 vm.overcommit_memory 11.2 修改redis的最大使用内存 修改配置文件 redis.conf maxmemory 1g…...
YOLOv5部署全场景问题解决方案手册(2025版)
YOLOv5部署全场景问题解决方案手册(2025版) 文章目录 YOLOv5部署全场景问题解决方案手册(2025版)[TOC]一、环境配置问题1.1 CUDA与PyTorch版本冲突1.2 依赖库缺失问题 二、模型转换问题2.1 ONNX导出失败2.2 TensorRT转换问题 三、…...
Canal 解析与 Spring Boot 整合实战
一、Canal 简介 1.1 Canal 是什么? Canal 是阿里巴巴开源的一款基于 MySQL 数据库增量日志解析(Binlog)中间件,它模拟 MySQL 的从机(Slave)行为,监听 MySQL 主机的二进制日志(Binl…...
AI第一天 自我理解笔记--微调大模型
目录 1. 确定目标:明确任务和数据 2. 选择预训练模型 3. 数据预处理 (1) 数据清洗与格式化 (2) 划分数据集 (4) 数据加载与批处理 4. 构建微调模型架构 (1) 加载预训练模型 (2) 修改模型尾部(适配任务) (3) 冻结部分层(…...
SpringBoot日志
目录 一、日志的用途 二、日志的使用 1.打印日志 2.在程序中得到日志对象 3.使用日志对象打印日志 4.日志格式说明 5.日志框架的了解 门面模式(外观模式) 6.日志级别 7.日志配置 配置日志级别 日志持久化 配置日志文件分割 配置日志格式 三、…...
Redis数据结构详解--列表
Redis 列表是简单的字符串列表,按照插入顺序排序,常用命令: LPUSH key value1 [value2...] 在列表头部插入一个或多个值RPUSH key value1 [value2...] 在列表尾部插入一个或多个值LPOP key 移除并获取列表头部第一个元素RPOP key 移除并获取…...
[项目]基于FreeRTOS的STM32四轴飞行器: 六.2.4g通信
基于FreeRTOS的STM32四轴飞行器: 六.2.4g通信 一.Si24Ri原理图二.Si24R1芯片手册解读三.驱动函数讲解五.移植2.4g通讯(飞控部分)六.移植2.4g通讯(遥控部分)七.通讯模块的完成(遥控部分)七.通讯模块的完成&a…...
ElasticSearch 7.x 集群 + Kibana 部署完全指南(5节点)
ElasticSearch 7.x 集群 Kibana 部署完全指南(5节点) 一、基础环境准备 1. 系统要求 CentOS 7/Ubuntu 18.04JDK 11(Elasticsearch 7自带JDK)内存:建议每个节点≥8GB磁盘:≥50GB(根据数据量调…...
前端项目中应该如何选择正确的图片格式
在前端项目中选择正确的图片格式是优化页面性能、提升用户体验的关键步骤之一。以下是常见图片格式的特点、适用场景及选择建议,帮助你在不同场景下做出最优决策: 一、常见图片格式对比 格式特点适用场景不适用场景JPEG- 有损压缩,文件小- 不…...
Python实现WYY音乐下载
一、需求背景 WYY音乐作为国内主流音乐平台,其歌曲资源丰富但下载接口存在多重加密保护。本文将通过Python结合JS逆向技术,解析其核心加密逻辑,实现免费歌曲的下载功能。 二、技术难点分析 1. 接口加密机制 通过抓包分析可知,网易云核心接口使用两次加密: 第一次:获取…...
药房链路轨道“空间拓扑优化+动态算法决策+多级容错控制”三重链式编程技术解析与应用
总论 随着智能医疗技术的快速发展,药房自动化系统已成为现代医院运营的核心基础设施。本文以“空间拓扑优化动态算法决策多级容错控制”三重链式编程技术为核心研究对象,探讨其如何通过跨学科技术融合实现药房链路轨道系统的精准化、高效化与可靠化运行…...
笔记本运行边缘计算
笔记本电脑可以用来运行PCDN(Peer-to-Peer Content Delivery Network)服务。实际上,如果你有闲置的笔记本电脑,并且它具备一定的硬件条件和网络环境,那么它可以成为一个不错的PCDN节点。 运行PCDN的基本要求 硬件需求…...
IMX8MP Android 10系统编译SDK
概述: 本文描述了在Ubuntu 20.04操作系统上搭建IMX8MP Android10系统编译环境。 ubuntu主机端设置 1. ubuntu 20.04 1. 450G Free Disk space 2. 16GB RAM以上 3. 安装 sudo apt-get install uuid uuid-dev zlib1g-dev liblz-dev liblzo2-2 liblzo2-dev lzop …...
项目实战:基于瑞萨RA6M5构建多节点OTA升级-创建系统最小框架<三>
MCUBoot项目创建完成后,接下来我们需要搭建多节点OTA系统最小框架,再将系统分模块搭建逐层完善,直到实现最终完整系统。开始动手干吧! 目录 一、创建项目 二、配置FSP 2.1 配置RS485属性 2.2 配置定时器0 2.3 创建初始化进程并配置属性 2.4 创建RS485进程并…...
汇能感知高品质的多光谱相机VSC02UA
VSC02UA概要 VSC02UA是一款高品质的200万像素的光谱相机,适用于工业检测、农业、医疗等领域。VSC02UA 包含 1600 行1200 列有源像素阵列、片上 10 位 ADC 和图像信号处理器。它带有 USB2.0 接口,配合专门的电脑上位机软件使用,可进行图像采集…...
Fisher 信息矩阵公式原理:使用似然估计,二阶导数等知识点
Fisher 信息矩阵公式原理:使用似然估计,二阶导数等知识点 目录 Fisher 信息矩阵公式原理:使用似然估计,二阶导数等知识点Fisher 通过似然估计求解真实数据和权重参数之间的差异**1. Fisher 信息矩阵的定义****2. 计算对数似然函数的二阶导数****3. 代入 Fisher 信息矩阵定义…...
Xilinx系列FPGA视频采集转HDMI2.0输出,基于HDMI 1.4/2.0 Transmitter Subsystem方案,提供6套工程源码和技术支持
目录 1、前言工程概述免责声明 2、相关方案推荐我已有的所有工程源码总目录----方便你快速找到自己喜欢的项目我已有的 GT 高速接口解决方案我已有的FPGA图像处理方案 3、详细设计方案设计框图硬件设计架构FPGA开发板输入Sensor之-->OV5640摄像头动态彩条Video In To AXI4-S…...
dify重磅升级:从0.15.3安全升级1.1.0新手避坑指南
Docker Compose 部署 备份自定义的 docker-compose YAML 文件(可选) cd docker cp docker-compose.yaml docker-compose.yaml.-$(date +%Y-%m-%d-%H-%M).bak从 main 分支获取最新代码 git checkout main git pull origin main停止服务,命令,请在 docker 目录下执行...
工业相机选型
工业相机选型 一、工业相机分类二、相机的主要参数2.1 分辨率2.2 速度2.3 光学接口 / 接口类型2.4 相机靶面尺寸2.5 像元尺寸2.6 精度 三、镜头介绍及选型方法3.1 工作距离(WD)3.2 视场角(FOV)3.3 (镜头)靶面尺寸3.4 帧率3.5 光圈…...
Vue3:构建高效用户界面的利器
一、Vue.js 简介 Vue.js(读音 /vjuː/, 类似于 view)是一套构建用户界面的渐进式框架。它只关注视图层,采用自底向上增量开发的设计。Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件 ,学习起来非常简单…...
mysql与redis的日志策略
MySQL 和 Redis 在日志记录方面采用了不同的策略,分别对应写前日志(Write-Ahead Logging, WAL)和写后日志(Write-After Logging)。以下是它们的详细说明: 1. MySQL:写前日志(Write-A…...
在 Spring Boot 中调用 AnythingLLM 的发消息接口
整体逻辑: 自建系统的web UI界面调用接口: 1.SpringBoot接口:/anything/chatMessageAnything 2.调用anythingLLM - 调用知识库deepseek r1 . Windows Installation ~ AnythingLLMhttps://docs.anythingllm.com/installation-desktop/windows http://localhost:3…...
Kotlin 基础语法
1. 🌟 Kotlin:Java 的“超级进化体”? Kotlin 是一门由 JetBrains 开发的 现代静态类型编程语言,支持 JVM、Android、JavaScript、Native 等多平台: Kotlin 与 Java 深度兼容,Kotlin 会编译为 JVM 字节码,…...
设计模式使用Java案例
代码设计要有可维护性,可复用性,可扩展性,灵活性,所有要使用设计模式进行灵活设计代码 创建型 简单工厂模式(Simple Factory) 简单工厂模式(Simple Factory Pattern)是一种创建型…...
LORA的AB矩阵是针对Transformer的多头还是MLP
LORA的AB矩阵是针对Transformer的多头还是MLP Transformer中的矩阵是一个整体还是分开的每个小矩阵 在LORA(Low-Rank Adaptation)中,AB矩阵的应用位置和Transformer中的矩阵拆分方式如下: 1. LORA的AB矩阵作用对象 LORA的AB矩阵主要作用于Transformer的多头注意力模块和…...
【Gitee】删除仓库的详细步骤
文章目录 1、点击个人主页2、点击仓库3、点击想要删除的仓库4、点击管理5、点击侧边栏的删除仓库 1、点击个人主页 进入gitee官网,登录后点击个人主页 2、点击仓库 点击仓库跳转,如下图所示: 3、点击想要删除的仓库 这个页面会展示你所…...