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

【落羽的落羽 C语言篇】指针·之其四

在这里插入图片描述

文章目录

  • 一、字符指针变量
  • 二、数组指针变量
    • 1. 创建
    • 2. 数组指针类型
    • 3. 二维数组传参的本质
  • 三、函数指针变量
    • 1. 创建
    • 2. 函数指针类型
    • 3. 函数指针的使用
    • 4. 分析两句“有趣”的代码(doge)
    • 5. typedef关键字
  • 四、函数指针数组
    • 1. 创建
    • 2. 函数指针数组的用途——转移表

一、字符指针变量

在讲到指针变量的类型时,我们知道有一种指针类型是字符指针char*
最简单的使用方法是:

int main()
{
char ch = 'a';
char* p = &ch;
*p = 'b';
return 0;
}

还有一种使用方式:

int main()
{
char* p = "hello world";
return 0;
}

第三行char* p = "hello world";,并不是把字符串hello world放到字符指针里了,而是把它的首字符h的地址放到了p中。

知道了这个,我们就能尝试分析一下下面这道题:

#include<stdio.h>
int main()
{
char arr1[]="abcde";
char arr2[]="abcde";
char* parr1="abcde";
char* parr2="abcde";
if(arr1 == arr2)printf("arr1 and arr2 are same\n");
elseprintf("arr1 and arr2 are not same\n");
if(parr1 == parr2)printf("parr1 and parr2 are same\n");
elseprintf("parr1 and parr2 are not same\n");return 0;
}

思考一下结果会是什么样的~
在这里插入图片描述

解析:arr1 == arr2比的是这两个数组首元素的地址,这两个数组是独立的,只是内容相同而已,数据存储的地址并不一样;而parr1 == parr2比的是两个指针变量中存放的地址,这两个指针指向的是同一个字符串abcde,所以是相同的

在这里插入图片描述
从本质上来讲:C语言会把常量字符串存储到单独的一个内存区域,当几个指针指向同一个字符串时,它们实际上会指向同一块内存区域。但是用相同的常量字符串去初始化不同的数组时就会开辟出不同的内存区域。
在这里插入图片描述

二、数组指针变量

1. 创建

在《指针·之其三》中,我们学习了指针数组。现在我们再来学习数组指针——指向数组的地址的指针变量。
数组指针变量的写法和前面的几种稍有不同,它的创建语法是数组元素类型(*指针名)[指向的数组的元素个数]比如:int(*p)[10],万万不能写成int* p[10]!因为[ ]的优先级高于*,所以必须写成(*p)来保证p先和*结合,以此说明p是指针变量,然后p指向的是一个大小为10的整形数组,p就是一个数组指针变量。

2. 数组指针类型

数组指针是用来存放数组的地址的,那怎么获得数组的地址呢?非常简单,使用我们之前提到的&数组名
在调试中也能看出来:&arr和p的类型是一样的

在这里插入图片描述那么,这个数组指针的具体类型又是什么呢?

我们知道,数组也有各种各样的类型,比如int arr1[10],char arr[8]等等,它们在元素类型和数组大小上都是不同的,所以数组指针变量也有不同的具体类型,怎么得到这些类型呢?

类比推理:
int* p1:p1的类型是int*,即是该句代码里去掉p1这个变量名;
char* p2:p2的类型是char*,即是该句代码里去p2这个变量名;

所以,int(*p)[10]:该句代码里去掉p这个变量名,int(*)[10]就是p的类型,p是一个存放10个整型的数组的数组指针。但虽然这就是p的类型,你也不能创建时就写成int(*)[10] p,这样程序会报错。王八的屁股——规定。

3. 二维数组传参的本质

有了数组指针的理解,我们就能学习二维数组传参的本质了。
在以前,我们想把二维数组传参给一个函数时,是这样写的:

#include<stdio.h>void test(int arr[3][5],int r,int c)
{
for(int i=0 ; ;i<r ; i++){for(int j=0 ; j<c ; j++)printf("%d ",a[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}};
test(arr,3,5);
return 0;
}

实参是二维数组,形参也是二维数组的形式。

然而,我们以前讲过,二维数组可以看成是每个元素都是一维数组的数组。也就是说,二维数组的首元素就是第一行,是一个一维数组。所以,根据数组名是数组首元素的地址这个规则,二维数组的数组名表示的就是第一行的地址,也就是一维数组的地址。根据上面的例子,第一行的一维数组的类型就是int [5],第一行的地址的类型就是int(*)[5]。这意味着,二维数组传参本质上也是传递了地址,传递的是第一行这个一维数组的地址。

由此,上面的函数参数部分就可以改变一下:

#include<stdio.h>void test(int(*p)[5],int r,int c)
{
for(int i=0 ; ;i<r ; i++){for(int j=0 ; j<c ; j++)printf("%d ", *(*(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}};
test(arr,3,5);
return 0;
}

关于*(*(p+i)+j)的理解:p+i是纵下标为 i 的一维数组的地址,*(p+i)是找到纵下标为 i 的一维数组,*(p+i)+j是该一维数组里下标为 j 的元素的地址,*(*(p+i)+j)就是该元素了

在这里插入图片描述

三、函数指针变量

1. 创建

函数也是有地址的,我们来观察一下:

在这里插入图片描述如图,函数test也是有地址的。

根据前面整型指针变量、数组指针变量的学习,我们不难知道:函数的地址存放在函数指针变量里。和数组名类似,函数名就是函数的地址当然也可以通过 &函数名 的方式获得函数的地址。
如果我们要存放函数的地址,当然也需要创建函数指针变量,它的写法和数组指针变量十分相似:函数返回类型(*指针变量名)(指向函数的参数),参数名可以省略。比如int(*p)(int x,int y)(x和y可以不写),p就是一个指向“有两个整型参数,返回类型是整型”的函数的函数指针变量。

2. 函数指针类型

这部分也和刚刚讲到的数组指针类型道理相同,创建一个函数指针变量时去掉函数名,就是这个函数指针变量的具体类型了。
比如上面的int(*p)(int x,int y),p的类型是int(*)(int x,int y)
灰常简单

3. 函数指针的使用

我们可以通过函数指针调用其指向的函数,假如指针变量p指向了函数test,那么*p和p都能表示test函数:

#include<stdio.h>
int Add(int x,int y)
{
return x+y;
}
int main()
{
int(*p)(int,int) = Add;
printf("%d\n", Add(2,4));
printf("%d\n", p(2,4));
printf("%d\n", (*p)(2,4));
return 0;
}

在这里插入图片描述结果都没有问题

4. 分析两句“有趣”的代码(doge)

  • 代码1:(*(void(*)())0)();
    相信所有人第一次见到它时,都是一脸懵,但这真的不是乱码,且看我画图分析:
    在这里插入图片描述但实际上,地址0是无法使用的,这其实是一个非法操作,仅仅是用来展示函数指针概念的。

  • 代码2:void(*signal(int,void(*)(int)))(int);
    在这里插入图片描述

通过这两段代码,想必大家对函数指针变量和函数指针类型有了更深刻的了解了吧,嘻嘻。
这两段代码都出自《C陷阱和缺陷》这本书,感兴趣可以去阅读一下~

5. typedef关键字

刚刚我们分析两段代码的过程是十分费劲的,归根结底是因为那些变量类型写起来太复杂了。而关键字typedef正好能解决这个问题,它是用来给类型重命名的,可以将复杂的类型简单化。用法是typedef 原类型 重命名;

举个栗子,你觉得long long int写起来不方便,如果能改成lli就好了,那么就可以有:

typedef long long int lli;

一般的类型和指针类型都可以这样用。但是对于数组指针类型和函数指针类型,稍微有点区别:新的类型必须写在*的后面。比如我们想把int(*)[5]重命名为parr_t,应该写成:

typedef int(*parr_t)[5];

我们想把void(*)(int)重命名为pf_t,应该写成:

typedef void(*pf_t)(int);

有了typedef这个工具,我们就可以简化上面的代码2:void(*signal(int,void(*)(int)))(int);

typedef void(*pf_t)(int);
//代码2就可以写成:
pf_t signal(int,pf_t);

在这里插入图片描述

四、函数指针数组

1. 创建

我们已经学了指针数组、函数指针,那么试试把它们组合起来吧——将函数的地址存放到数组中,这就是函数指针数组,它该如何定义呢?答案是:将数组名和大小写在函数指针类型的*后。

比如,创建一个数组parr,能存放3个元素,元素类型是“有一个整型参数,无返回类型”的函数指针类型。就应该写成:void(*parr[3])(int)

2. 函数指针数组的用途——转移表

函数指针数组最常见的用途就是转移表。转移表是一种数据结构,它根据输入值来确定需要执行的函数或操作。
一个实例:实现一个计算器,要能根据你的选择进行加减乘除运算。
经过思考,我们可以分布实现:

  • 分别定义加减乘除的函数:
int add(int a,int b)
{
return a+b;
}int sub(int a,int b)
{
return a-b;
}int mul(int a,int b)
{
return a*b;
}int div(int a,int b)
{
return a/b;
}
  • 创建函数指针数组,存放这四个函数
int(*p[5])(int,int)={ 0 , add , sub , mul , div };
//0的作用是让四个函数的下标能和下面的选项对应起来
  • 设定菜单选项
printf("----------------------\n");
printf("----1.add    2.sub----\n");
printf("----3.mul    4.div----\n");
printf("--------0.quit--------\n");
printf("----------------------\n");
printf("请选择:");
  • 根据输入的选项,决定执行函数
scanf("%d",&option);
if((option<=4)&&(option>=1))
{
printf("输入操作数:");
scanf("%d %d",&x,&y);
ret = (*p[option])(x,y);
printf("结果是%d\n",ret);
}
else if(option==0)return 0;
elseprintf("输入错误");

最后,把上面的所有东西结合起来,并且让它不退出一直可以选择计算:

#include<stdio.h>
int add(int a,int b)
{
return a+b;
}
int sub(int a,int b)
{
return a-b;
}
int mul(int a,int b)
{
return a*b;
}
int div(int a,int b)
{
return a/b;
}int main()
{
int(*p[5])(int,int)={ 0 , add , sub , mul , div };
int x,y;
int ret=0;
int option=0;while(1)
{
printf("----------------------\n");
printf("----1.add    2.sub----\n");
printf("----3.mul    4.div----\n");
printf("--------0.quit--------\n");
printf("----------------------\n");
printf("请选择:");
scanf("%d",&option);
if((option<=4)&&(option>=1)){printf("输入操作数:");scanf("%d %d",&x,&y);ret = (*p[option])(x,y);printf("结果是%d\n",ret);}
else if(option==0)return 0;
elseprintf("输入错误\n");
}
//一个很巧妙的点是,我并没有将return 0放在最后,这样程序只会在option==0的情况下结束,结束前while(1)会让它一直运行
}

这样,程序就很完美了
在这里插入图片描述

欲知后事如何,且听下回分解~
在这里插入图片描述
本篇完,感谢阅读

相关文章:

【落羽的落羽 C语言篇】指针·之其四

文章目录 一、字符指针变量二、数组指针变量1. 创建2. 数组指针类型3. 二维数组传参的本质 三、函数指针变量1. 创建2. 函数指针类型3. 函数指针的使用4. 分析两句“有趣”的代码&#xff08;doge&#xff09;5. typedef关键字 四、函数指针数组1. 创建2. 函数指针数组的用途—…...

十二、正则表达式、元字符、替换修饰符、手势和对话框插件、字符串截取

1. 正则表达式 1.1 基本使用 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title&g…...

嵌入式的应用领域有哪些

首先给大家介绍一下‌‌&#xff0c;STM32是‌意法半导体&#xff08;STMicroelectronics&#xff09;生产的32位微控制器&#xff08;‌MCU&#xff09;系列‌&#xff0c;采用‌ARM Cortex-M内核设计&#xff0c;以其高性能、低功耗和广泛的应用而闻名。‌ 那么意法半导体是在…...

git merge :开发分支与主分支的交互

一、开发分支&#xff08;dev&#xff09;上的代码达到上线的标准后&#xff0c;要合并到 master 分支 git checkout dev git pull git checkout master git merge dev git push -u origin master 二、当master代码改动了&#xff0c;需要更新开发分支&#xff08;dev&#x…...

OGRE 3D----4. OGRE和QML共享opengl上下文

在现代图形应用开发中,OGRE(Object-Oriented Graphics Rendering Engine)和QML(Qt Modeling Language)都是非常流行的工具。OGRE提供了强大的3D渲染能力,而QML则用于构建灵活的用户界面。在某些应用场景中,我们需要在同一个应用程序中同时使用OGRE和QML,并且共享OpenGL…...

ArcGIS 软件中路网数据的制作

内容导读 路网数据是进行网络分析的基础&#xff0c;它是建立网络数据集的数据来源。 本文我们以OSM路网数据为例&#xff0c;详细介绍OSM路网数据从下载&#xff0c;到数据处理&#xff0c;添加属性&#xff0c;完成符合网络分析的网络数据集的全部过程。 01 数据获取 比较…...

Milvus 2.5:全文检索上线,标量过滤提速,易用性再突破!

01. 概览 我们很高兴为大家带来 Milvus 2.5 最新版本的介绍。 在 Milvus 2.5 里&#xff0c;最重要的一个更新是我们带来了“全新”的全文检索能力&#xff0c;之所以说“全新”主要是基于以下两点&#xff1a; 第一&#xff0c;对于全文检索基于的 BM25 算法&#xff0c;我们采…...

Windows常用DOS指令(附案例)

文章目录 1.dir 查看当前目录2.cd 进入指定目录3.md 创建指定目录4.cd> 创建指定文件5.rd 删除指定空目录6.del 删除指定文件7.copy 复制文件8.xcopy 批量复制9.ren 改名10.type 在命令行空窗口打开文件11.cls 清空DOS命令窗口12.chkdsk 检查磁盘使用情况13.time 显示和设置…...

搜索二维矩阵 II(java)

题目描述 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性&#xff1a; 每行的元素从左到右升序排列。每列的元素从上到下升序排列。 代码思路&#xff1a; 用暴力算法&#xff1a; class Solution {public boolean searchMatrix(…...

Webpack 的构建流程

Webpack 的构建流程可以概括为以下几个步骤&#xff1a; 1. 初始化&#xff1a; Webpack 读取配置文件&#xff08;webpack.config.js&#xff09;&#xff0c;合并默认配置和命令行参数&#xff0c;初始化Compiler对象。 2. 构建依赖图&#xff1a; 从入口文件开始递归地分…...

Kylin Server V10 下 RocketMQ 主备自动切换模式部署

一、NameServer简介 NameServer 是一个注册中心,提供服务注册和服务发现的功能。NameServer 可以集群部署,集群中每个节点都是对等的关系,节点之间互不通信。 服务注册 Broker 启动的时候会向所有的 NameServer 节点进行注册,注意这里是向集群中所有的 NameServer 节点注册…...

Linux启动中出现“psi: inconsistent task state!”错误可能原因

在Linux系统中&#xff0c;psi: inconsistent task state! 异常日志通常与 PSI&#xff08;Pressure Stall Information&#xff09;相关。PSI 是 Linux 内核中的一个特性&#xff0c;用于监控系统资源的压力情况&#xff0c;如 CPU、内存和 I/O 等。该日志信息表明在处理任务状…...

FCBP 认证考试要点摘要

理论知识 数据处理与分析&#xff1a;包括数据的收集、清洗、转换、存储等基础操作&#xff0c;以及数据分析方法&#xff0c;如描述性统计分析、相关性分析、数据挖掘算法等的理解和应用 。数据可视化&#xff1a;涉及图表类型的选择与应用&#xff0c;如柱状图、折线图、饼图…...

ubuntu防火墙入门(一)——设置服务、关闭端口

本机想通过git clone gitgithub.com:skumra/robotic-grasping.git下载代码&#xff0c;firewall-config中需要为当前区域的防火墙开启SSH服务吗 是的&#xff0c;如果你想通过 git clone gitgithub.com:skumra/robotic-grasping.git 使用 SSH 协议从 GitHub 下载代码&#xff0…...

yt6801 ubuntu有线连接驱动安装

耀世16pro的有线网卡驱动安装 下载地址: YT6801 千兆PCIE以太网控制器芯片 1. 创建安装目录 mkdir yt68012. 解压驱动文件 unzip yt6801-linux-driver-1.0.27.zip -d yt68013. 进入驱动目录 cd yt68014. 安装驱动 以 root 权限运行安装脚本&#xff1a; sudo su ./yt_ni…...

ASP.NET Core Web API 控制器

文章目录 一、基类&#xff1a;ControllerBase二、API 控制器类属性三、使用 Get() 方法提供天气预报结果 在深入探讨如何编写自己的 PizzaController 类之前&#xff0c;让我们先看一下 WeatherController 示例中的代码&#xff0c;了解它的工作原理。 在本单元中&#xff0c;…...

【论文笔记】Tool Learning with Foundation Models 论文笔记

Tool Learning with Foundation Models 论文笔记 文章目录 Tool Learning with Foundation Models 论文笔记摘要背景&#xff1a;工作&#xff1a; 引言工具学习的发展本文工作&#xff08;大纲&目录&#xff09; 背景2.1 工具使用的认知起源2.2 工具分类&#xff1a;用户界…...

STM32 + CubeMX + 串口 + IAP升级

这篇文章分享一个简单的串口IAP Demo&#xff0c;实现使用串口更新我们自己的App程序。 目录 一、IAP简介二、Stm32CubeMx配置三、Boot代码及配置1、代码2、配置 四、App代码及配置1、代码2、配置 五、效果展示 一、IAP简介 IAP介绍可以在网上找找&#xff0c;相关资料很多&am…...

Oracle-—系统包使用

文章目录 系统包dbms_redefinition 系统包 dbms_redefinition 功能介绍&#xff1a;该包体可以实现将Oracle库下的表在线改为分区结构或者重新定义&#xff1b; 说明&#xff1a;在检查表是否可以重定义和开始重定义的过程中&#xff0c;按照表是否存在主键&#xff0c;参数 o…...

使用Hugo和GitHub Pages创建静态网站个人博客

不需要服务器&#xff0c;不需要域名&#xff0c;不需要数据库&#xff0c;可以选择模版&#xff0c;内容为Markdown格式。 Hugo&#xff1a;https://gohugo.io 文档&#xff1a;https://gohugo.io/getting-started/quick-start/ 中文文档&#xff1a;https://www.gohugo.or…...

群晖系统证书延期

群晖系统默认证书过期了 接下来操作续期证书 一直下一步会让下载一个压缩包里面包含私钥和签发证书请求 下载后解压出来 在群晖里用证书续期 对以前的证书签署签发请求 选择刚刚解压出来的证书 执行完成后会下载一个压缩包&#xff0c;解压出来就会得到新证书 给群晖新增证书 选…...

android shader gl_Position是几个分量

在Android的OpenGL ES中&#xff0c;gl_Position是顶点着色器&#xff08;Vertex Shader&#xff09;的一个内置输出变量&#xff0c;它用于指定顶点在裁剪空间&#xff08;Clip Space&#xff09;中的位置。gl_Position是一个四维向量&#xff08;4-component vector&#xff…...

JAVA练习-ArrayList数组

需求 建立3个Student类的实例 原始数组&#xff1a; public class Student {private String name;private int score;public Student(String name, int score) {this.name name;this.score score;}Overridepublic String toString() {return name "的分数&#xff1…...

springboot339javaweb的新能源充电系统pf(论文+源码)_kaic

毕 业 设 计&#xff08;论 文&#xff09; 题目&#xff1a;新能源充电系统的设计与实现 摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解…...

数据结构——排序第三幕(深究快排(非递归实现)、快排的优化、内省排序,排序总结)超详细!!!!

文章目录 前言一、非递归实现快排二、快排的优化版本三、内省排序四、排序算法复杂度以及稳定性的分析总结 前言 继上一篇博客基于递归的方式学习了快速排序和归并排序 今天我们来深究快速排序&#xff0c;使用栈的数据结构非递归实现快排&#xff0c;优化快排&#xff08;三路…...

Jackson:Java对象和JSON字符串的转换处理库使用指南

Jackson介绍 Jackson 是一个非常流行的 Java JSON 处理库&#xff0c;它能够将 Java 对象与 JSON 字符串相互转换。 Jackson 工具主要用于将请求的参数&#xff08;例如前端发送的 JSON 数据&#xff09;和响应的数据&#xff08;例如后端返回给前端的数据&#xff09;转换成…...

mac maven编译出现问题

背景 进行maven install 命令&#xff0c;报错&#xff1a; [ERROR] COMPILATION ERROR : [INFO] ------------------------------------------------------------- [ERROR] No compiler is provided in this environment. Perhaps you are running on a JRE rather than a J…...

深入讲解Spring Boot和Spring Cloud,外加图书管理系统实战!

很抱歉&#xff0c;我的疏忽&#xff0c;说了这么久还没有给大家详细讲解过Spring Boot和Spring Cloud,那今天给大家详细讲解一下。 大家可以和下面这三篇博客一起看&#xff1a; 1、Spring Boot 和 Spring Cloud 微服务开发实践详解https://blog.csdn.net/speaking_me/artic…...

【AIGC】2023-ICCV-用于高保真语音肖像合成的高效区域感知神经辐射场

2023-ICCV-Efficient Region-Aware Neural Radiance Fields for High-Fidelity Talking Portrait Synthesis 用于高保真语音肖像合成的高效区域感知神经辐射场摘要1. 引言2. 相关工作3. 方法3.1 准备工作和问题设置3.2 三平面哈希表示3.3. 区域注意模块3.4 训练细节 4. 实验4.1…...

如何写一份优质技术文档

作者简介&#xff1a; 本文作者拥有区块链创新专利30&#xff0c;是元宇宙标准化工作组成员、香港web3标准工作组成员&#xff0c;参与编写《数据资产确权与交易安全评价标准》、《链接元宇宙&#xff1a;应用与实践》、《香港Web3.0标准化白皮书》等标准&#xff0c;下面提供…...

ML 系列:第 35 节 - 机器学习中的数据可视化

ML 系列&#xff1a;第 35 天 - 机器学习中的数据可视化 文章目录 一、说明二、数据可视化2.1 直方图2.2 箱线图2.3 散点图2.4 条形图2.5 线图2.6 热图 三、结尾 一、说明 描述性统计和数据可视化是理解和解释机器学习数据的基础。它们有助于总结和直观地呈现数据&#xff0c…...

存储服务器一般做是做什么阵列?详细列举一下

存储服务器通常使用 RAID&#xff08;Redundant Array of Independent Disks&#xff09; 阵列技术来管理磁盘&#xff0c;以提高数据的性能、可靠性和可用性。所选择的 RAID 类型取决于存储服务器的具体用途和需求&#xff0c;比如性能要求、容量需求、容错能力等。 以下是存…...

uniapp使用扩展组件uni-data-select出现的问题汇总

前言 不知道大家有没有学习过我的这门课程那&#xff0c;《uniCloud云开发Vue3版本官方推荐用法》&#xff0c;这么课程已经得到了官方推荐&#xff0c;想要快速上手unicloud的小伙伴们&#xff0c;可以学习一下这么课程哦&#xff0c;不要忘了给一键三连呀。 在录制这门课程…...

pdf.js 预览pdf的时候发票数据缺失显示不全:字体加载出错(缺失)导致部分缺失

首先&#xff0c;排除后端返回的PDF文件流是没有问题的&#xff1a; 但是在vue项目中是这样的&#xff1a; 明显是显示不全&#xff0c;F12查看报错信息&#xff0c;有以下警告&#xff1a; pdf.js:2153 Warning: Error during font loading: The CMap “baseUrl” paramet…...

【设计模式】【结构型模式(Structural Patterns)】之外观模式(Facade Pattern)

1. 设计模式原理说明 外观模式&#xff08;Facade Pattern&#xff09; 是一种结构型设计模式&#xff0c;它提供了一个统一的接口&#xff0c;用来访问子系统中的一群接口。外观模式定义了一个高层接口&#xff0c;这个接口使得这一子系统更加容易使用。通过隐藏子系统的复杂…...

Redis使用场景-缓存-缓存穿透

前言 之前在针对实习面试的博文中讲到Redis在实际开发中的生产问题&#xff0c;其中缓存穿透、击穿、雪崩在面试中问的最频繁&#xff0c;本文加了图解&#xff0c;希望帮助你更直观的了解缓存穿透&#x1f600; &#xff08;放出之前写的针对实习面试的关于Redis生产问题的博…...

介绍 Apache Spark 的基本概念和在大数据分析中的应用

Apache Spark 是一个开源的大数据处理框架&#xff0c;它提供了快速、通用、可扩展的数据处理能力。Spark可以处理大规模数据集&#xff0c;并且在内存中进行数据操作&#xff0c;从而实现高速的数据处理和分析。 Spark的核心概念是弹性分布式数据集&#xff08;Resilient Dis…...

OpenCPN-插件之Dashboard Tactics

1&#xff1a;相关链接Dashboard Tactics :: OpenCPN Dashboard Tactics Plugin rgleason/dashboard_tactics_pi: OpenCPN dashboard built-in plugin merger with external tactics_pi plugin NMEAconverter :: OpenCPN 2&#xff1a;显示样式 3&#xff1a;代码 这个插件…...

【LeetCode面试150】——20有效的括号

博客昵称&#xff1a;沈小农学编程 作者简介&#xff1a;一名在读硕士&#xff0c;定期更新相关算法面试题&#xff0c;欢迎关注小弟&#xff01; PS&#xff1a;哈喽&#xff01;各位CSDN的uu们&#xff0c;我是你的小弟沈小农&#xff0c;希望我的文章能帮助到你。欢迎大家在…...

JWT介绍和结合springboot项目实践(登录、注销授权认证管理)

目录 一、JWT介绍&#xff08;一&#xff09;基本介绍&#xff08;二&#xff09;jwt有哪些库1、jjwt&#xff08;Java JWT&#xff09;2、nimbus - jwt - jwt - api 和 nimbus - jwt - jwt - impl3、spring - security - jwt&#xff08;已弃用&#xff0c;但在旧项目中有参考…...

Linux 下安装 Golang环境

Linux 下安装 Golang 获取Golang下载地址 安装 进入终端&#xff0c;登入root来到应用安装目录使用 wget 下载解压文件配置环境变量查看golang版本&#xff0c;测试是否配置成功GO设置代理环境变量 本篇教程 以 centos7 为环境基础 不使用软件包管理器安装&#xff0c;原因&am…...

「Mac畅玩鸿蒙与硬件36」UI互动应用篇13 - 数字滚动抽奖器

本篇将带你实现一个简单的数字滚动抽奖器。用户点击按钮后&#xff0c;屏幕上的数字会以滚动动画的形式随机变动&#xff0c;最终显示一个抽奖数字。这个项目展示了如何结合定时器、状态管理和动画实现一个有趣的互动应用。 关键词 UI互动应用数字滚动动画效果状态管理用户交…...

安装使用Ubuntu18.04超级大全集最初版(anaconda,pycharm,代理,c/c++环境)

本文介绍ubuntu1804中我目前用到的环境的完整配置&#xff0c;包括ubuntu安装软件&#xff0c;更新环境变量等都有涉及。图片非常多&#xff0c;能给的连接和材料都给了。希望能帮助到新同学。 目录 目录 目录 环境及镜像文件 安装Ubuntu ​编辑 开机之后 ​编辑 更新…...

Redis设计与实现第16章 -- Sentinel 总结1(初始化、主从服务器获取信息、发送信息、接收信息)

Sentinel是Redis的高可用解决方案&#xff1a;由一个或多个Sentinel实例组成的Sentinel系统可以监视任意多个主服务器&#xff0c;以及这些主服务器属下的所有从服务器&#xff0c;被监视的主服务器进入下线状态时&#xff0c;自动将下线主服务器属下的某个从服务器升级为新的主…...

ChatGPT科研应用、论文写作、课题申报、数据分析与AI绘图

随着人工智能技术的飞速发展&#xff0c;ChatGPT等先进语言模型正深刻改变着科研工作的面貌。从科研灵感的激发、论文的高效撰写&#xff0c;到课题的成功申报&#xff0c;乃至复杂数据的深度分析与可视化呈现&#xff0c;AI技术均展现出前所未有的潜力。其实众多科研前沿工作者…...

OceanBase数据库系列之:基于docker快速安装OceanBase数据库,基于linux服务器快速部署OceanBase数据库

OceanBase数据库系列之&#xff1a;基于docker快速安装OceanBase数据库&#xff0c;基于linux服务器快速部署OceanBase数据库 一、docker快速安装OceanBase数据库下载OceanBase数据库镜像查看镜像启动OceanBase数据库查看OceanBase数据库是否启动成功 二、基于linux部署OceanBa…...

无星的微前端之旅(四)——qiankun线上服务代理到本地

这个方式其实是我在上家公司的时候体验过&#xff0c;觉得确实很有意思。 所以这里来逆推一下实现方式。 解决了什么痛点 1.开发一个模块&#xff0c;需要启动2-3个项目 在微前端的开发过程中&#xff0c;如果我们要在主应用中看效果&#xff0c;我们至少需要启动一个主应用&am…...

鸿蒙进阶篇-Stage模型、UIAbility

“在科技的浪潮中&#xff0c;鸿蒙操作系统宛如一颗璀璨的新星&#xff0c;引领着创新的方向。作为鸿蒙开天组&#xff0c;今天我们将一同踏上鸿蒙基础的探索之旅&#xff0c;为您揭开这一神奇系统的神秘面纱。” 各位小伙伴们我们又见面了,我就是鸿蒙开天组,下面让我们进入今…...

快速上手:如何开发一个实用的 Edge 插件

在日常浏览网页时&#xff0c;背景图片能够显著提升网页的视觉体验。如果你也想为自己的浏览器页面添加个性化背景图片&#xff0c;并希望背景图片设置能够持久保存&#xff0c;本文将介绍如何通过开发一个自定义Edge插件来实现这一功能。我们将涵盖保存背景设置到插件选项页&a…...

java缓存技术点介绍

1. 缓存&#xff08;Cache&#xff09;&#xff1a; • 缓存是指用于存储数据的临时存储区域&#xff0c;以便快速访问。在Java中&#xff0c;缓存通常用于存储频繁访问的对象、结果集或其他数据。 2. 缓存命中率&#xff08;Cache Hit Ratio&#xff09;&#xff1a; • 缓存命…...