【C语言】指针详解(3)
大家好,我是苏貝,本篇博客带大家了解指针(2),如果你觉得我写的还不错的话,可以给我一个赞👍吗,感谢❤️
目录
- 一.函数指针数组
- 二.指向函数指针数组的指针(不重要)
- 三.回调函数
一.函数指针数组
字符数组–数组–存放字符的数组
整型数组–数组–存放整型的数组
指针数组–数组–存放指针的数组
函数指针数组–数组–存放函数指针的数组,即存放函数的地址
int (* parr1[10])();
parr1 先和 [ ] 结合,说明 parr1是数组,数组的元素类型是什么呢?将数组名和数组名后面的[ ] 去掉,得到int (* )(),即函数指针,所以数组的元素类型是函数指针
函数指针数组的用途:转移表
例子:计算器,实现+ - * / 4个功能
#include<stdio.h>void menu()
{printf("********************************\n");printf("****** 1.Add 2.Sub ******\n");printf("****** 3.Mul 4.Div ******\n");printf("****** 0.exit ******\n");printf("********************************\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 input = 0;int x = 0;int y = 0;int ret = 0;do{menu();printf("请选择:");scanf("%d", &input);switch (input){case 1:printf("请输入2个数:");scanf("%d %d", &x, &y);ret = Add(x, y);printf("%d\n", ret);break;case 2:printf("请输入2个数:");scanf("%d %d", &x, &y);ret = Sub(x, y);printf("%d\n", ret);break;case 3:printf("请输入2个数:");scanf("%d %d", &x, &y);ret = Mul(x, y);printf("%d\n", ret);break;case 4:printf("请输入2个数:");scanf("%d %d", &x, &y);ret = Div(x, y);printf("%d\n", ret);break;case 0:printf("退出程序\n");break;default:printf("选择错误,请重新选择:\n");break;}} while (input);return 0;
}
但是写完这些代码后我们发现,这些代码有许多重复的地方,所以我们是否可以简化一下呢?
简化上面的代码,我们发现,Add,Sub,Mul,Div的参数类型和个数相同,返回类型也相同,所以可以使用函数指针数组,让Add,Sub,Mul,Div成为该数组的元素,用数组的元素调用Add,Sub,Mul,Div函数;
int(*pfArr [ ])(int, int) = { Add,Sub,Mul,Div };
所以它们的下标分别为0,1,2,3,但由于菜单上1,2,3,4才代表它们,所以我们不妨在Add前加NULL,这样它们的下标就为1,2,3,4了
int(*pfArr[])(int, int) = { NULL,Add,Sub,Mul,Div };
总代码:
#include<stdio.h>void menu()
{printf("********************************\n");printf("****** 1.Add 2.Sub ******\n");printf("****** 3.Mul 4.Div ******\n");printf("****** 0.exit ******\n");printf("********************************\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 input = 0;int x = 0;int y = 0;int ret = 0;do{menu();printf("请选择:");scanf("%d", &input);int(*pfArr[])(int, int) = { NULL,Add,Sub,Mul,Div };if (0 == input)printf("退出程序\n");else if (input >= 1 && input <= 4){printf("请输入2个数:");scanf("%d %d", &x, &y);ret = pfArr[input](x, y);printf("%d\n", ret);}elseprintf("输入错误,请重新输入\n");} while (input);return 0;
}
上述代码也有缺陷,因为要写成数组元素的话,它们的类型必须要相同,如果有一个函数,它的返回类型不是int,那就不能采用这种方法
二.指向函数指针数组的指针(不重要)
经过上面的学习,我们可以知道,指向函数指针数组的指针是一个 指针,指针指向一个 数组 ,数组的元素都是 函数指针,那指向函数指针数组的指针该如何定义呢?
void(*(*p)[2])(int, int);
p先与 * 结合,代表p是个指针,再与[ ]结合,表示p指向的是个数组,将( * p)[2]去掉得到void( *)(int, int)是函数指针,所以数组的元素类型是函数指针
int Add(int x, int y)
{return x + y;
}int Sub(int x, int y)
{return x - y;
}int main()
{//函数指针int (*pf)(int, int) = Add;//函数指针数组int (*pfArr[2])(int, int) = { Add,Sub };//指向函数指针数组的指针int(*(*p)[2])(int, int);return 0;
}
三.回调函数
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应
例子:计算器(将上面最开始的计数器代码优化)

我们可以看出,上面红色框里面的大部分代码都冗余,那我们能否使用一个函数cacl()达到实现+ - * / 4个功能的目的呢?
思路:将实现+ - * / 4个功能的函数作为函数cacl()的形参,用一个函数指针来接收
void menu()
{printf("********************************\n");printf("****** 1.Add 2.Sub ******\n");printf("****** 3.Mul 4.Div ******\n");printf("****** 0.exit ******\n");printf("********************************\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 cacl(int (*pf)(int, int))
{int x = 0;int y = 0;int ret = 0;printf("请输入2个数:");scanf("%d %d", &x, &y);ret = pf(x, y);printf("%d\n", ret);
}int main()
{int input = 0;do{menu();printf("请选择:");scanf("%d", &input);switch (input){case 1:cacl(Add);break;case 2:cacl(Sub);break;case 3:cacl(Mul);break;case 4:cacl(Div);break;case 0:printf("退出程序\n");break;default:printf("选择错误,请重新选择:\n");break;}} while (input);return 0;
}
先使input==2,所以选择的是减法,输入使得x=10,y=2,通过函数指针pf找到Sub函数,返回8用ret接收,最后输出ret

好了,那么本篇博客就到此结束了,如果你觉得本篇博客对你有些帮助,可以给个大大的赞👍吗,感谢看到这里,我们下篇博客见❤️
相关文章:
【C语言】指针详解(3)
大家好,我是苏貝,本篇博客带大家了解指针(2),如果你觉得我写的还不错的话,可以给我一个赞👍吗,感谢❤️ 目录 一.函数指针数组二.指向函数指针数组的指针(不重要)三.回调函数 一.函…...
告别HR管理繁琐,免费低代码平台来帮忙
编者按:本文着重介绍了使用免费且高效的低代码平台实现的HR管理系统在一般日常人力资源管理工作中的关键作用。 关键词:低代码平台、HR管理系统 1.HR管理系统有什么作用? HR管理系统作为一款数字化工具,可为企业提供全方位的人力资…...
Java开发面试--Redis专区
1、 什么是Redis?它的主要特点是什么? 答: Redis是一个开源的、基于内存的高性能键值对存储系统。它主要用于缓存、数据存储和消息队列等场景。 高性能:Redis将数据存储在内存中,并采用单线程的方式处理请求…...
Ansible-roles学习
目录 一.roles角色介绍二.示例一.安装httpd服务 一.roles角色介绍 roles能够根据层次型结构自动装载变量文件,tasks以及handlers登。要使用roles只需在playbook中使用include指令即可。roles就是通过分别将变量,文件,任务,模块以…...
python3如何安装各类库的小总结
我的python3的安装路径是: C:\Users\Administrator\AppData\Local\Programs\Python\Python38 C:\Users\Administrator\AppData\Local\Programs\Python\Python38\python3.exeC:\Users\Administrator\AppData\Local\Programs\Python\Python38\Scripts C:\Users\Admin…...
ffmpeg 特效 转场 放大缩小
案例 ffmpeg \ -i input.mp4 \ -i image1.png \ -i image2.png \ -filter_complex \ [1:v]scale100:100[img1]; \ [2:v]scale1280:720[img2]; \ [0:v][img1]overlay(main_w-overlay_w)/2:(main_h-overlay_h)/2[bkg];\ [bkg][img2]overlay0:0 \ -y output.mp4 -i input.mp4//这…...
【GNN 03】PyG
工具包安装: 不要pip安装 https://github.com/pyg-team/pytorch_geometrichttps://github.com/pyg-team/pytorch_geometric import torch import networkx as nx import matplotlib.pyplot as pltdef visualize_graph(G, color):plt.figure(figsize(7, 7))plt.xtic…...
每日刷题-5
目录 一、选择题 二、算法题 1、不要二 2、把字符串转换成整数 一、选择题 1、 解析:printf(格式化串,参数1,参数2,.….),格式化串: printf第一个参数之后的参数要按照什么格式打印,比如%d--->按照整形方式打印&am…...
RNN简介(深入浅出)
目录 简介1. 基本理论 简介 要快速掌握RNN,可以考虑以下步骤: 学习基本理论:了解RNN的原理、结构和工作原理。掌握RNN的输入输出形式、时间步、隐藏状态、记忆单元等关键概念。学习常见的RNN变体:了解LSTM(Long Shor…...
Leetcode137. 某一个数字出现一次,其余数字出现3次
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。 你必须设计并实现线性时间复杂度的算法且使用常数级空…...
原子化CSS(Atomic CSS)
UnoCSS,它不是像TailWind CSS和Windi CSS属于框架,而是一个引擎,它没有提供预设的原子化CSS工具类。引用自掘金,文章中实现相同的功能,构建后的体积TailWind 远> Windi > UnoCSS,体积会小很多。 像这种原子性的…...
pandas 筛选数据的 8 个骚操作
日常用Python做数据分析最常用到的就是查询筛选了,按各种条件、各种维度以及组合挑出我们想要的数据,以方便我们分析挖掘。 东哥总结了日常查询和筛选常用的种骚操作,供各位学习参考。本文采用sklearn的boston数据举例介绍。 from sklearn …...
【随想】每日两题Day.3(实则一题)
题目:59.螺旋矩阵|| 给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 示例 1: 输入:n 3 输出:[[1,2,3],[8,9,4],[7,6,5]]示例 2: …...
阿里后端开发:抽象建模经典案例【文末送书】
文章目录 写作前面1.抽象思维2.软件世界中的抽象3. 经典抽象案例4. 抽象并非一蹴而就!需要不断假设、验证、完善5. 推荐一本书 写作末尾 写作前面 在互联网行业,软件工程师面对的产品需求大都是以具象的现实世界事物概念来描述的,遵循的是人…...
HarmonyOS Codelab 优秀样例——溪村小镇(ArkTS)
一、介绍 溪村小镇是一款展示溪流背坡村园区风貌的应用,包括园区内的导航功能,小火车行车状态查看,以及各区域的风景展览介绍,主要用于展示HarmonyOS的ArkUI能力和动画效果。具体包括如下功能: 打开应用时进入启动页&a…...
Mybatis---第二篇
系列文章目录 文章目录 系列文章目录一、#{}和${}的区别是什么?二、简述 Mybatis 的插件运行原理,如何编写一个插件一、#{}和${}的区别是什么? #{}是预编译处理、是占位符, KaTeX parse error: Expected EOF, got # at position 27: …接符。 Mybatis 在处理#̲{}时,会将…...
6.2.3 【MySQL】InnoDB的B+树索引的注意事项
6.2.3.1 根页面万年不动窝 B 树的形成过程是这样的: 每当为某个表创建一个 B 树索引(聚簇索引不是人为创建的,默认就有)的时候,都会为这个索引创建一个 根节点 页面。最开始表中没有数据的时候,每个 B 树…...
前端面试话术集锦第 12 篇:高频考点(Vue常考基础知识点)
这是记录前端面试的话术集锦第十二篇博文——高频考点(Vue常考基础知识点),我会不断更新该博文。❗❗❗ 这一章节我们将来学习Vue的一些经常考到的基础知识点。 1. 生命周期钩子函数 在beforeCreate钩子函数调用的时候,是获取不到props或者data中的数据的,因为这些数据的…...
骨传导耳机危害有哪些?值得入手吗?
事实上,只要是正常使用,骨传导耳机并不会对身体造成伤害,并且在众多耳机种类中,骨传导耳机可以说是相对健康的一种耳机,这种耳机最独特的地方便是声波不经过外耳道和鼓膜, 而是直接将人体骨骼结构作为传声介…...
网络爬虫-----初识爬虫
目录 1. 什么是爬虫? 1.1 初识网络爬虫 1.1.1 百度新闻案例说明 1.1.2 网站排名(访问权重pv) 2. 爬虫的领域(为什么学习爬虫 ?) 2.1 数据的来源 2.2 爬虫等于黑客吗? 2.3 大数据和爬虫又有啥关系&…...
JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...
初探Service服务发现机制
1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源…...
LangFlow技术架构分析
🔧 LangFlow 的可视化技术栈 前端节点编辑器 底层框架:基于 (一个现代化的 React 节点绘图库) 功能: 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...
软件工程 期末复习
瀑布模型:计划 螺旋模型:风险低 原型模型: 用户反馈 喷泉模型:代码复用 高内聚 低耦合:模块内部功能紧密 模块之间依赖程度小 高内聚:指的是一个模块内部的功能应该紧密相关。换句话说,一个模块应当只实现单一的功能…...
C++--string的模拟实现
一,引言 string的模拟实现是只对string对象中给的主要功能经行模拟实现,其目的是加强对string的底层了解,以便于在以后的学习或者工作中更加熟练的使用string。本文中的代码仅供参考并不唯一。 二,默认成员函数 string主要有三个成员变量,…...
EEG-fNIRS联合成像在跨频率耦合研究中的创新应用
摘要 神经影像技术对医学科学产生了深远的影响,推动了许多神经系统疾病研究的进展并改善了其诊断方法。在此背景下,基于神经血管耦合现象的多模态神经影像方法,通过融合各自优势来提供有关大脑皮层神经活动的互补信息。在这里,本研…...

