【c语言】深入理解指针2
文章目录
- 一、指针数组
- 指针数组模拟二维数组
- 二、数组指针
- 二维数组传参的本质
- 三、字符指针变量
- 四、函数指针变量
- 4.1. 函数指针的应用
- 4.2 两端有趣的代码
- 4.3. typedef关键字
- 4.3.1 typedef 的使用
- 4.3.2. typedef与#define对比
- 五、函数指针数组
- 函数指针数组的应用
一、指针数组
指针数组到底是指针还是数组呢?
整型数组 int arr[] : 存放整型的数组;
字符数组 char arr[] : 存放字符的数组;
可以类比得到:
指针数组 int* arr[] : 存放指针的数组.
因此,指针数组本质上是数组,数组中的每个元素都存放的是地址(指针),每个元素的类型为指针类型.
示例:下方代码中
parr先和 [ ] 结合,因此它是一个数组,这个数组有3个元素,每个元素的类型为int*
int arr1[5] = { 1,2,3,4,5 };
int arr2[5] = { 1,2,3,4,5 };
int arr3[5] = { 1,2,3,4,5 };
int* parr[3] = {arr1,arr2,arr3};
将数组名去掉就可以看出它的类型,即int* [3]
,也就是指针数组
指针数组模拟二维数组
int main()
{//创建三个整型数组int arr1[5] = { 1,2,3,4,5 };int arr2[5] = { 1,2,3,4,5 };int arr3[5] = { 1,2,3,4,5 };//由于数组名就是数组首元素地址,将每个数组名存放到指针数组parr中int* parr[3] = {arr1,arr2,arr3};int i = 0;for (i = 0;i < 3;i++)//遍历三个数组名{int j = 0;for (j = 0;j < 5;j++)//遍历每个数组{printf("%d ", parr[i][j]);}printf("\n");}return 0;
}
对 parr [ i ] [ j ] 进行解释:
- parr [ i ] 访问的是parr中的元素,找到的是第 i 个数组名,指向一维整形数组.
比如 parr [ 0 ]找到的是 arr1, parr [ 1 ]找到的是 arr2, parr [ 2 ]找到的是 arr3, 因此 parr [ 0 ] 就是arr1数组名,本质就是第一个数组首元素地址- parr [ i ] [ j ] 指向一维数组中的元素,找到的是第 i 个数组的第 j 个元素.
比如parr [ 0 ] [ 0 ] == arr1 [ 0 ] == 1- arr1, arr2, arr3本质上是指针,因此可以存到指针数组 parr 中.
- parr模拟的二维数组并非是真正的二维数组,因为二维数组在内存中是连续存放的.
二、数组指针
数组指针到底是数组还是指针呢?
整型指针
int* p = &a
: p 是存放整型变量地址、指向整型变量的指针;
字符指针char* pc = 'c'
: pc 是存放字符变量地址、指向字符变量的指针;
浮点型指针float* pf = &f
: pf 是存放浮点型变量地址、指向浮点型变量的指针;
数组指针:int (*p) [ 5 ] = &arr
: p 是指向整型数组的指针.
因此,数组指针本质上是指针,是指向数组的指针,存放的是数组的地址
示例:
int arr[] = { 1,2,3 };
int (*p)[3] = &arr;
- p先与*结合,说明p是一个指针变量,然后与 [ ] 结合,说明它指向的是一个数组,数组中有三个元素,每个元素的类型为
int
- 数组指针的初始化:数组指针存的是数组的地址,因此将整个数组取地址赋值给数组指针就可以
指针数组与数组指针的区分:
指针数组是存放指针的数组,“指针”是定语,修饰“数组”
数组指针是指向数组的指针,“数组”是定语,修饰“指针”
二维数组传参的本质
int arr[3][5] = { { 1,2,3,4,5 }, {2,3,4,5,6},{3,4,5,6,7 } }
arr[3][5]可以看作是一个有三个元素的一维数组,每个元素是一个一维数组,第一个元素是{1,2,3,4,5},第二个元素是{2,3,4,5,6},第三个元素是{3,4,5,6,7},因此,遵循数组名是数组首元素地址的原则,那么认为二维数组的数组名其实就是第一行数组的地址,数组的地址类型为数组指针,那么二维数组传参的本质传递的是第一行数组的地址,需要用数组指针类型来接收
用数组指针来打印二维数组
void print(int (*p)[5])
{int i = 0;for (i = 0;i < 3;i++){for (int j = 0;j < 5;j++){printf("%d ", *(*(p + i) + j));//也可以写成p[i][j]}printf("\n");}
}
int main()
{int arr[3][5] = { { 1,2,3,4,5 }, {2,3,4,5,6},{3,4,5,6,7 } };print(arr);return 0;
}
p 是数组指针,
p + i
得到的是第 i 行元素的地址,*( p + i )
得到的是第 i 行元素的数组名,*( p + i ) + j
得到的是第 i 行第 j 个元素的地址,再进行解引用就得到该元素
有人会问,p + i
是地址,*( p + i )
得到的应该是数据,*( p + i ) + j
得到的还是数字,*(*( p + i ) + j)
就是对数字进行解引用,没有意义了.
实际上 p + i 是二维数组中第 i 行数组的地址,那么 p + 0 == p == arr [ 0 ], 以第一行数组为例,第一行数组是一维数组,arr [ 0 ] [ j ] 得到的是第一行数组第 j 个元素,那么arr [ 0 ]本质上就是第一行数组的数组名,也就是第一行数组首元素 1 的地址. 因此
*(p + i)
实际得到的是第 i 行的数组名,本质还是地址,想得到 i 行 j 列 这个元素需要*(*(p + i) + j).
二维数组在想象中是以行和列形式存在的,但是在内存中的存储是连续的, 因此只需要知道首元素地址就可以连续访问
当然,二维数组传参,形参部分也可以写成二维数组(不能省略列),也可以写成数组指针形式.
三、字符指针变量
char* a = "abcdef";
其中,a是一个字符指针,存放的是字符串第一个字符的地址,并不是整个字符串的地址,并且该字符串为常量字符串,不能被改变,因此严谨来说应该在前加上const
const char* a = "abcdef";
示例:
int main()
{char str1[] = "hello bit.";char str2[] = "hello bit.";const char* str3 = "hello bit.";const char* str4 = "hello bit.";if (str1 == str2)printf("str1 and str2 are same\n");elseprintf("str1 and str2 are not same\n");if (str3 == str4)printf("str3 and str4 are same\n");elseprintf("str3 and str4 are not same\n");
- str3 和 str4 是两个相同的常量字符串, 在内存中只会开辟一块内存空间,不同的指针指向相同的常量字符串的时候,指向的是同一块内存空间,因此 str3 和 str4 是相同的
- 用相同的常量字符串去初始化两个字符数组,内存会为两个数组单独开辟两个内存空间,因此str1和str2是不同的,他们分别指向两个不同的地址
四、函数指针变量
函数指针:指向函数的指针,存放的是函数的地址.
首先了解什么是函数的地址:
void test()
{printf("666\n");
}
int main()
{test();printf("test = %p\n", test);printf("&test = %p\n", &test);return 0;
}
可以看出,函数名 test 和 &test 的地址是一样的,因此函数名就表示函数的地址,想存储函数的地址,就需要函数指针变量
函数指针的初始化:
int Add(int x, int y)
{return x + y;
}
int (*pf1)(int, int) = Add;
int (*pf2)(int, int) = &Add;
Add是一个函数,pf1 (pf2) 先与*结合,表明其是一个指针,然后与后面的( )结合,表明其指向的是一个函数,函数内部的参数有两个,分别都是 int 类型,函数的返回类型是 int 型.
去掉变量名pf1,就可以看出他的类型是 int ( * ) ( int , int )
函数指针类型
4.1. 函数指针的应用
用函数指针实现两个数相加:
可以看出,上述三种方法都可以实现Add函数的调用
- 直接用函数名调用函数.
- 利用函数指针 pf 取得Add函数的地址,然后对其解引用*pf得到函数名,再进行调用.
- 直接用函数指针pf进行调用.
总结:函数名Add实际就是函数的地址,函数指针pf也是函数的地址,函数名直接调用函数就相当于用地址调用函数,那么直接用pf调用,不解引用也是可以的
比如:
实际上可以看出:
005513CF为函数Add的地址
函数指针pf,*pf得到的都是005513CF,即函数Add的地址,因此利用函数指针调用函数的时候可以不用解引用,直接进行调用
4.2 两端有趣的代码
1.第一段代码
(*(void (*)())0)();
从内部向外看
- 黄色部分
void ( * ) ( )
,表明类型为函数指针类型- 蓝色括号 ( ) 0,表示将整型 0 强制类型转换成函数指针类型,得到的是一个地址 00000000,意味着我们假设0地址处放着无参,返回类型为void的函数
- 绿色括号内部是对其进行解引用,得到的是该地址处的函数名
- 右侧黑色括号表示调用这个函数
因此调用的是0地址处的函数,函数的返回类型为void,函数参数为无参
- 第二段代码
void (*signal(int, void(*)(int)))(int);
signal,先与后面接的蓝色括号结合,表明它指向一个函数,说明它是一个函数名,该函数内部有两个参数,类型分别是 整型int 和 函数指针类型
void(*)(int)
,然后将函数名和函数参数去掉可以得到:
函数还缺一个返回类型,因此该函数的返回类型为函数指针类型
将这段代码改写以下就可以更清楚看到:
- signal 是函数名,指向的函数内部有两个参数,参数类型分别是整型和函数指针类型,该函数的返回类型为函数指针类型
- 这种写法只是便于分析,在编译器中这种写法是不允许的,只能写成第一种形式
4.3. typedef关键字
4.3.1 typedef 的使用
如果类型写起来太复杂,我们可以将其重新定义,进行简化,比如
将unsigned int 重命名为uint
typedef unsigned int uint;
对于指针数组来说,正确的重命名为 parr_t 的方式是,parr_t 必须在 * 的右边
typedef int(*parr_t)[5]
同样对于函数指针,将其重命名为pfun_t,必须放在*的右边
typedef void(*pfun_t)(int,void(*)())//新的类型名必须放在*的右边
pfun_t signal(int,pfun_t);//对代码进行简化
4.3.2. typedef与#define对比
typedef int* ptr_t;
ptr_t p1,p2;
将
int*
类型重命名为ptr_t ,p1, p2
均为指针变量
#define PTR_t int*
PTR_t p1,p2;
将PTR_t 定义为int* 类型,那么p1为指针变量,p2为整型变量 ,因为替换之后为:
int* p1, p2
,是一个逗号表达式,*只会与p1结合
五、函数指针数组
函数指针数组:存放函数指针的数组,本质是一个数组,用来存放函数指针变量.
函数指针数组的定义:
int (* parr [ 3 ] ) ( );
parr先与[ ]结合,表明它是一个数组,该数组有3个元素,每个元素的类型为函数指针类型
int ( * ) ( )
函数指针数组的应用
转移表的实现:
实现一个具有加减乘除的计算器:
void menu()
{printf("1.add 2. sub \n");printf("3.mul 4. div \n");printf("0.exit \n");
}
int Add(int x, int y)
{return x + y;
}
int Sub(int x, int y)
{return x - y;
}
int Mul(int x, int y)
{return x * y;
}
int Div(int x, int y)
{return x / y;
}int main()
{int a = 0;int b = 0;int input = 0;int ret = 0;do {menu();printf("请选择:");scanf_s("%d", &input);switch (input){case 1:printf("请输入两个参数:");scanf_s("%d %d", &a, &b);ret = Add(a, b);printf("%d \n", ret);break;case 2:printf("请输入两个参数:");scanf_s("%d %d", &a, &b);ret = Sub(a, b);printf("%d \n", ret);break;case 3:printf("请输入两个参数:");scanf_s("%d %d", &a, &b);ret = Mul(a, b);printf("%d \n", ret);case 4:printf("请输入两个参数:");scanf_s("%d %d", &a, &b);ret = Div(a, b);printf("%d \n", ret);break;case 0:printf("退出\n");break;default:printf("请重新输入:");break;}} while (input);return 0;
}
通过选择1、2、3、4实现计算器的运算,但是这种方法有一个缺点,每一个case下面几乎都是相同的功能,唯独不同的就是进行函数的调用,因此我们应该想办法将这一重复的功能封装成一个函数去实现
利用函数指针数组实现计算器:
void menu()
{printf("1.add 2. sub \n");printf("3.mul 4. div \n");printf("0.exit \n");
}
int Add(int x, int y)
{return x + y;
}
int Sub(int x, int y)
{return x - y;
}
int Mul(int x, int y)
{return x * y;
}
int Div(int x, int y)
{return x / y;
}int main()
{int a = 0;int b = 0;int input = 0;int ret = 0;int (*pf[5])(int, int) = { 0,Add,Sub,Mul,Div };do {menu();printf("请选择:");scanf_s("%d", &input);if (input <= 4 && input >= 1){printf("请输入操作数:");scanf_s("%d %d", &a, &b);ret = pf[input](a,b);printf("%d\n", ret);}else if(input==0){printf("退出\n");}else{printf("重新输入");}} while (input);return 0;
}
利用函数指针实现转移表:
将重复的功能封装到calc函数中实现,通过函数指针调用加减乘除函数
main是主调函数,calc函数是被调函数,具体实现加减乘除功能的函数为回调函数
void menu()
{printf("1.add 2. sub \n");printf("3.mul 4. div \n");printf("0.exit \n");
}
int Add(int x, int y)
{return x + y;
}
int Sub(int x, int y)
{return x - y;
}
int Mul(int x, int y)
{return x * y;
}
int Div(int x, int y)
{return x / y;
}
void calc(int (*pf)(int, int))
{int a, b;printf("请输入两个参数:");scanf_s("%d %d", &a, &b);int ret = pf(a, b);printf("%d \n", ret);
}
int main()
{int a = 0;int b = 0;int input = 0;int ret = 0;do {menu();printf("请选择:");scanf_s("%d", &input);switch (input){case 1:calc(Add);break;case 2:calc(Sub);break;case 3:calc(Mul);case 4:calc(Div);break;case 0:printf("退出\n");break;default:printf("请重新输入:");break;}} while (input);return 0;
}
相关文章:
【c语言】深入理解指针2
文章目录 一、指针数组指针数组模拟二维数组 二、数组指针二维数组传参的本质 三、字符指针变量四、函数指针变量4.1. 函数指针的应用4.2 两端有趣的代码4.3. typedef关键字4.3.1 typedef 的使用4.3.2. typedef与#define对比 五、函数指针数组函数指针数组的应用 一、指针数组 …...
Nacos
Nacos是阿里巴巴的产品, 现在是SpringCloud中的一个组件。相比Eureka功能更加丰富,在国内受欢迎程度较高。 官网地址:Redirecting to: https://nacos.io/ GitHub: https://github.com/alibaba/nacos 1.Nacos快入门 Nacos可以直…...
Linux,redis群集模式,主从复制,读写分离
redis的群集模式 主从模式 (单项复制,主复制到从) 一主两从 一台主机上的一主两从 需要修改三个配置文件 主要端口不一样 redis-8001.conf redis-8002.conf redis-8003.conf 哨兵模式 分布式集群模式 redis 安装部署 1,下载…...
《手环表带保养全攻略:材质、清洁与化学品避坑指南》
系列文章目录 文章目录 系列文章目录前言一、表带材质特性与专属养护方案二、清洁剂使用红黑榜三、家庭清洁实验:化学反应警示录四、保养实践方法论总结 前言 手环作为现代生活的智能伴侣,表带材质选择丰富多样。从柔软亲肤的皮质到耐用耐磨的金属&…...
【Leetcode 每日一题 - 补卡】1534. 统计好三元组
问题背景 给你一个整数数组 a r r arr arr,以及 a 、 b 、 c a、b 、c a、b、c 三个整数。请你统计其中好三元组的数量。 如果三元组 ( a r r [ i ] , a r r [ j ] , a r r [ k ] ) (arr[i], arr[j], arr[k]) (arr[i],arr[j],arr[k]) 满足下列全部条件ÿ…...
医疗设备预测性维护合规架构:从法规遵循到技术实现的深度解析
在医疗行业数字化转型加速推进的当下,医疗设备预测性维护已成为提升设备可用性、保障医疗安全的核心技术。然而,该技术的有效落地必须建立在严格的合规框架之上。医疗设备直接关乎患者生命健康,其维护过程涉及医疗法规、数据安全、质量管控等…...
如何在 IntelliJ IDEA 中安装 FindBugs-IDEA 1.0.1
以下是 FindBugs-IDEA 1.0.1 插件在 IntelliJ IDEA 中的安装步骤(适用于较旧版本的 IDEA,新版本可能需使用替代插件如 SpotBugs): 方法一:手动下载安装(适用于无法通过市场安装的情况) 下载插件…...
小车正常但是加载不出地图 找不到mapserver
Request for map failed; trying again... 找不到mapserver 原因: bash [ERROR] [1744895448.714854952]: failed to open image file "/home/liyb/catkin_ws/src/nav_demo/map/crossing.pgm": Couldnt open /home/xxx/catkin_ws/src/nav_demo/map/cr…...
无头开发模式
“无头”开发模式(Headless Development Mode)是指在没有直接连接物理显示器(monitor)、键盘或鼠标等输入输出设备的情况下,通过远程工具(如 SSH、SCP、rsync、VNC 或 Web 界面)对设备进行开发、…...
DAY 47 leetcode 232--栈与队列.用栈实现队列
题号232 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty): class MyQueue {Stack<Integer> stackIn;Stack<Integer> stackOut;/** Initialize your data structure here. */pu…...
SpringAI+DeepSeek大模型应用开发——4 对话机器人
目录 项目初始化 pom文件 配置模型 ChatClient 同步调用 流式调用 日志功能 对接前端 解决跨域 会话记忆功能 ChatMemory 添加会话记忆功能 会话历史 管理会话id 保存会话id 查询会话历史 完善会话记忆 定义可序列…...
leetcode0058. 最后一个单词的长度-easy
1 题目:最后一个单词的长度 官方标定难度:易 给你一个字符串 s,由若干单词组成,单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。 单词 是指仅由字母组成、不包含任何空格字符的最大子字符串。 示例 1&#x…...
深入理解 Linux top 命令:从字段解读到性能诊断
系统或产品都需要部署到服务器或容器上运行,而服务器的运行效率直接影响到系统的稳定性和用户体验。因此,服务器的性能监控与分析就显得尤为重要。 在实际运维和性能测试过程中,我们可以从以下关键的几个方面入手进行系统监控与分析(网络延迟分析暂时先略过): CPU 使用率…...
[特殊字符] UnionFS(联合文件系统)原理解析:容器背后的存储技术
🔍 UnionFS(联合文件系统)原理解析:容器背后的存储技术 💡 什么是 UnionFS? UnionFS(联合文件系统) 是一种可以将多个不同来源的文件系统“合并”在一起的技术。它的核心思想是&am…...
部署若依前后端分离
参考部署:https://blog.csdn.net/qq_46073825/article/details/128716794?spm1001.2014.3001.5502 1.连接mysql(windows版本) 2.更新数据库用户为远程可连接 3.redis下载地址 https://github.com/tporadowski/redis/releases 5执行npm init 或者npm install --r…...
用Python Pandas高效操作数据库:从查询到写入的完整指南
一、环境准备与数据库连接 1.1 安装依赖库 pip install pandas sqlalchemy psycopg2 # PostgreSQL # 或 pip install pandas sqlalchemy pymysql # MySQL # 或 pip install pandas sqlalchemy # SQLite 1.2 创建数据库引擎 通过SQLAlchemy创建统一接口:…...
eventBus 事件中心管理组件间的通信
EventBus(事件总线)是Vue中用于实现非父子组件间通信的轻量级方案,通过一个中央Vue实例管理事件的发布与订阅。 一、基本使用步骤 1.创建EventBus实例 推荐单独创建文件(如event-bus.js)导出实例,避免全…...
某客户ORA-600 导致数据库反复重启问题分析
上班期间,收到业务反馈,测试环境数据库连接报错。 查看数据库alert日志,发现从中午的时候就出现了重启。并且在17时20分左右又发生了重启: 同时,在重启前alert日志中出现了ORA-600报错,相关报错在trc文件中…...
LeetCode 2176.统计数组中相等且可以被整除的数对:两层遍历模拟
【LetMeFly】2176.统计数组中相等且可以被整除的数对:两层遍历模拟 力扣题目链接:https://leetcode.cn/problems/count-equal-and-divisible-pairs-in-an-array/ 给你一个下标从 0 开始长度为 n 的整数数组 nums 和一个整数 k ,请你返回满足…...
Vue项目Webpack Loader全解析:从原理到实战配置指南
Vue项目Webpack Loader全解析:从原理到实战配置指南 前言 在Vue项目的开发与构建中,Webpack Loader扮演着资源转换的核心角色。无论是单文件组件(SFC)的解析、样式预处理,还是静态资源的优化,都离不开Loa…...
Vscode --- LinuxPrereqs │远程主机可能不符合 glibc 和 libstdc++ Vs code 服务器的先决条件
打开vscode连接远程linux服务器,发现连接失败,并出现如下报错信息: 原因是: vscode 官网公告如下:2025 年 3 月 (版本 1.99) - VSCode 编辑器 版本1.97 官网公告如下:链接 版本1.98 官网公告如下&am…...
大数据常见的模型定义及应用场景建议╮(╯▽╰)╭
以下是常见的大数据模型类型及其分析方法: 1. 描述性模型 1.1 定义 描述性模型:用于描述数据的现状和历史趋势,帮助理解数据的特征和模式。 1.2 常见模型 统计摘要:均值、中位数、标准差等。数据可视化:直方图、散…...
红宝书第四十八讲:实时通信双雄:Socket.IO Meteor 的奇妙旅程
红宝书第四十八讲:实时通信双雄:Socket.IO & Meteor 的奇妙旅程 资料取自《JavaScript高级程序设计(第5版)》。 查看总目录:红宝书学习大纲 一、实时通信基础 1. WebSocket与HTTP对比 传统HTTP请求类似送信&…...
【数字图像处理】图像分割(1)
图像分割定义 把图像分成若干个特定的、具有独特性质的区域,并提出感兴趣目标的技术和过程 图像分割概述 一幅图像通常是由代表物体的图案与背景组成,简称物体与背景 图像分割的本质:将图像按照区域内的一致性和区域间的不一致性进行分类的过…...
VFlash的自动化和自定义动作
文章目录 一、automation 自动化二、custom actions 自定义动作常用方法如何选择要发送的诊断请求CustomActionValueList 作用Pre Action和Post Action之间交换信息 提示:如何打印软件中变量报错:无法打开源文件 Windows.h stdio.h conio.h报错ÿ…...
pytorch学习02
自动微分 自动微分模块torch.autograd负责自动计算张量操作的梯度,具有自动求导功能。自动微分模块是构成神经网络训练的必要模块,可以实现网络权重参数的更新,使得反向传播算法的实现变得简单而高效。 1. 基础概念 张量 Torch中一切皆为张…...
TV板卡维修技术【四】
【一】热成像松香的结合快速定位短路位置 发现电路短路,但是无法定位到大概位置,可以采用烧机法: 热成像大致定位,松香准确定位: 可以很快找到这种小陶瓷电容短路的故障: 测量电路是否有大短路,…...
Rust生命周期、文件与IO
文章目录 Rust生命周期生命周期注释结构体如何使用字符串静态生命周期 Rust文件与IO接收命令行参数命令行输入文件读取文件写入 Rust生命周期 终于讲到Rust最重要的机制之一了,生命周期机制 我们先复习一下垂悬引用 {let r;{let x 5;r &x;}println!("…...
22、字节与字符的概念以及二者有什么区别?
1、概念 字节(byte) 定义:字节是计算机信息技术中用于计量存储容量和传输容量的一种单位,通常由8个二进制位(bit)组成。 作用:字节是计算机存储和处理信息的基本单位,用于衡量数据…...
APP端测试
一、功能测试 1. 核心测试点 安装/卸载/升级:验证不同安装方式(应用商店/APK/IPA) 注册登录:多种登录方式测试(手机号、第三方账号) 核心业务流程:支付流程、内容发布等关键路径 中断测试&a…...
Langchain-构建向量数据库和检索器
向量数据库安装 pip install langchain-chroma 文档》向量存储》向量数据库。 和0416 提示词工程相同。 初始化 import osfrom langchain_chroma import Chroma from langchain_community.chat_message_histories import ChatMessageHistory from langchain_core.documents im…...
PPT无法编辑怎么办?原因及解决方法全解析
在日常办公中,我们经常会遇到需要编辑PPT的情况。然而,有时我们会发现PPT文件无法编辑,这可能由多种原因引起。今天我们来看看PPT无法编辑的几种常见原因,并提供实用的解决方法,帮助你轻松应对。 原因1:文…...
PH热榜 | 2025-04-17
1. Mailgo 标语:一款利用人工智能的冷邮件平台,能够提升邮件送达率。 介绍:Mailgo将AI线索寻找助手、智能日程安排和预热账户集成到一个直观的平台上——帮助销售团队和创业者高效到达客户邮箱,轻松扩展业务,并加快转…...
maptalks矩形绘制结束后,获取最大经度最大纬度,最小经度最小纬度,从左上角开始依次获取并展示坐标
maptalks矩形绘制结束后,获取最大经度最大纬度,最小经度最小纬度,从左上角开始依次获取并展示坐标 重点 // 获取绘制的矩形图形对象const rectangle param.geometry;// 获取矩形外接矩形范围(西南角/东北角坐标)cons…...
网页图像优化:现代格式与响应式技巧
网页图像优化:现代格式与响应式技巧 网页图像如果处理不好,很容易拖慢加载速度,影响用户体验。这篇文章聊聊怎么用现代图像格式和响应式技巧,让你的网站图片加载更快、效果更好。 推荐的图像格式 选对图像格式,能在保…...
python中参数前**的含义
在Python中,参数前的 ** 表示该参数是一个“关键字参数”或者说是“可变关键字参数”。这种参数允许函数接受任意数量的关键字参数,并将这些参数存储在一个名为**kwargs的字典中。这使得函数可以接收任意数量的键值对参数,这在编写需要处理多…...
内存编码手册:整数与浮点数的二进制世界
1.整数在内存中的存储 之前在学习操作符的博文中,我们就已经学习了整数在内存中存储的一些基本知识,我们来快速回忆一下,并开始学习新的知识。 之前的学习中,我们知道整数的二进制表示方法有三种,即原码,…...
铷元素的市场供需情况如何?
铷元素的市场供需格局呈现出显著的稀缺性与战略价值,其供应高度依赖锂矿开采的副产品,而需求则随着高科技产业的快速发展持续攀升。以下从供应、需求、价格、政策及可持续性五个维度展开分析: 一、供应端:资源稀缺与技术瓶颈并存…...
MATLAB 程序实现了一个层次化光网络的数据传输模拟系统
% 主程序 num_pods = 4; % Pod 数量 num_racks_per_pod = 4; % 每个 Pod 的 Rack 数量 num_nodes_per_rack = 4; % 每个 Rack 的 Node 数量 max_wavelength = 50; % 可用波长数(根据冲突图动态调整) num_packets = 1000; % 模拟的…...
LFI to RCE
LFI不止可以来读取文件,还能用来RCE 在多道CTF题目中都有LFItoRCE的非预期解,下面总结一下LFI的利用姿势 1. /proc/self/environ 利用 条件:目标能读取 /proc/self/environ,并且网页中存在LFI点 利用方式: 修改请…...
QT6 源(34):随机数生成器类 QRandomGenerator 的源码阅读
(1)代码来自 qrandom.h ,结合官方的注释: #ifndef QRANDOM_H #define QRANDOM_H#include <QtCore/qalgorithms.h> #include <algorithm> // for std::generate #include <random> // for std::mt1993…...
极狐GitLab GEO 功能介绍
极狐GitLab 是 GitLab 在中国的发行版,关于中文参考文档和资料有: 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 Geo (PREMIUM SELF) Geo 是广泛分布的开发团队的解决方案,可作为灾难恢复策略的一部分提供热备份。Geo 不是 开箱…...
快速上手,OceanBase + MCP + LLM,搭建 AI 应用
在 AI 技术发展的进程中,大语言模型(LLM)凭借卓越的信息处理与推理能力广受重视。然而,数据孤岛问题仍是 LLM 面临的核心挑战。目前,LLM 的推理主要依赖于预先训练的数据和有限的上下文窗口,既无法动态访问…...
【Python爬虫基础篇】--1.基础概念
目录 1.爬虫--定义 2.爬虫--组成 3.爬虫--URL 1.爬虫--定义 网络爬虫,是一种按照一定规则,自动抓取互联网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。随着网络的迅速发展,万维网成为大量信息的载体…...
Linux :进程替换
进程替换 (一)进程程序替换1.替换原理2.替换函数exec函数命名理解 (二)实现简易shell (一)进程程序替换 1.替换原理 用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往…...
XC7K410T‑2FFG900I 赛灵思XilinxFPGA Kintex‑7
XC7K410T‑2FFG900I Xilinx 赛灵思FPGA Kintex‑7 系列定位:Kintex‑7 中端,高性价比与高性能平衡 工艺节点:28 nm HPL(High‑Performance, Low‑Power)HKMG(High‑κ Metal Gate) 逻辑资源&…...
list容器介绍及模拟实现和与vector比较
目录 list容器介绍 lisy接口 list迭代器的注意事项 迭代器失效 list的模拟实现 list的节点 list的迭代器实现 list的接口实现 vector和list的优缺点 vector优点: vector缺点: list优点: list缺点: 总结: …...
[图论]Prim
Prim 本质:BFS贪心,对点进行操作。与最短路Dijkstra算法是“孪生兄弟”。存储结构:链式前向星适用对象:可为负权图,可求最大生成树核心思想:最近的邻接点一定在最小生成树(MST)上,对点的最近邻…...
【python】pysharm常用快捷键使用-(1)
*1.格式化代码【Ctrl Alt L】 写代码的时候会有很多黄色的波浪号(如图)又叫蚂蚁线,可以点击任意黄色波浪号的代码,然后按下【Ctrl Alt L】进行代码格式化。 2.添加函数功能和参数注释 添加函数文档字符串 docstring 在函数…...
06-DevOps-自动构建Docker镜像
前面已经完成了jar文件的打包和发布,但在实际使用时,可能会遇到外部依赖环境发生改变,为了解决这些问题,更多的做法是把应用程序以docker镜像,生成容器的方式运行,这是一种标准化的方式。 创建Dockerfile文…...