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

【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)

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家了解指针(2)&#xff0c;如果你觉得我写的还不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 目录 一.函数指针数组二.指向函数指针数组的指针&#xff08;不重要&#xff09;三.回调函数 一.函…...

告别HR管理繁琐,免费低代码平台来帮忙

编者按&#xff1a;本文着重介绍了使用免费且高效的低代码平台实现的HR管理系统在一般日常人力资源管理工作中的关键作用。 关键词&#xff1a;低代码平台、HR管理系统 1.HR管理系统有什么作用&#xff1f; HR管理系统作为一款数字化工具&#xff0c;可为企业提供全方位的人力资…...

Java开发面试--Redis专区

1、 什么是Redis&#xff1f;它的主要特点是什么&#xff1f; 答&#xff1a; Redis是一个开源的、基于内存的高性能键值对存储系统。它主要用于缓存、数据存储和消息队列等场景。 高性能&#xff1a;Redis将数据存储在内存中&#xff0c;并采用单线程的方式处理请求&#xf…...

Ansible-roles学习

目录 一.roles角色介绍二.示例一.安装httpd服务 一.roles角色介绍 roles能够根据层次型结构自动装载变量文件&#xff0c;tasks以及handlers登。要使用roles只需在playbook中使用include指令即可。roles就是通过分别将变量&#xff0c;文件&#xff0c;任务&#xff0c;模块以…...

python3如何安装各类库的小总结

我的python3的安装路径是&#xff1a; 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

工具包安装&#xff1a; 不要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、 解析&#xff1a;printf(格式化串&#xff0c;参数1&#xff0c;参数2,.….)&#xff0c;格式化串: printf第一个参数之后的参数要按照什么格式打印&#xff0c;比如%d--->按照整形方式打印&am…...

RNN简介(深入浅出)

目录 简介1. 基本理论 简介 要快速掌握RNN&#xff0c;可以考虑以下步骤&#xff1a; 学习基本理论&#xff1a;了解RNN的原理、结构和工作原理。掌握RNN的输入输出形式、时间步、隐藏状态、记忆单元等关键概念。学习常见的RNN变体&#xff1a;了解LSTM&#xff08;Long Shor…...

Leetcode137. 某一个数字出现一次,其余数字出现3次

力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 给你一个整数数组 nums &#xff0c;除某个元素仅出现 一次 外&#xff0c;其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。 你必须设计并实现线性时间复杂度的算法且使用常数级空…...

原子化CSS(Atomic CSS)

UnoCSS&#xff0c;它不是像TailWind CSS和Windi CSS属于框架&#xff0c;而是一个引擎&#xff0c;它没有提供预设的原子化CSS工具类。引用自掘金&#xff0c;文章中实现相同的功能&#xff0c;构建后的体积TailWind 远> Windi > UnoCSS,体积会小很多。 像这种原子性的…...

pandas 筛选数据的 8 个骚操作

日常用Python做数据分析最常用到的就是查询筛选了&#xff0c;按各种条件、各种维度以及组合挑出我们想要的数据&#xff0c;以方便我们分析挖掘。 东哥总结了日常查询和筛选常用的种骚操作&#xff0c;供各位学习参考。本文采用sklearn的boston数据举例介绍。 from sklearn …...

【随想】每日两题Day.3(实则一题)

题目&#xff1a;59.螺旋矩阵|| 给你一个正整数 n &#xff0c;生成一个包含 1 到 n2 所有元素&#xff0c;且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;[[1,2,3],[8,9,4],[7,6,5]]示例 2&#xff1a; …...

阿里后端开发:抽象建模经典案例【文末送书】

文章目录 写作前面1.抽象思维2.软件世界中的抽象3. 经典抽象案例4. 抽象并非一蹴而就&#xff01;需要不断假设、验证、完善5. 推荐一本书 写作末尾 写作前面 在互联网行业&#xff0c;软件工程师面对的产品需求大都是以具象的现实世界事物概念来描述的&#xff0c;遵循的是人…...

HarmonyOS Codelab 优秀样例——溪村小镇(ArkTS)

一、介绍 溪村小镇是一款展示溪流背坡村园区风貌的应用&#xff0c;包括园区内的导航功能&#xff0c;小火车行车状态查看&#xff0c;以及各区域的风景展览介绍&#xff0c;主要用于展示HarmonyOS的ArkUI能力和动画效果。具体包括如下功能&#xff1a; 打开应用时进入启动页&a…...

Mybatis---第二篇

系列文章目录 文章目录 系列文章目录一、#{}和${}的区别是什么?二、简述 Mybatis 的插件运行原理,如何编写一个插件一、#{}和${}的区别是什么? #{}是预编译处理、是占位符, KaTeX parse error: Expected EOF, got # at position 27: …接符。 Mybatis 在处理#̲{}时,会将…...

6.2.3 【MySQL】InnoDB的B+树索引的注意事项

6.2.3.1 根页面万年不动窝 B 树的形成过程是这样的&#xff1a; 每当为某个表创建一个 B 树索引&#xff08;聚簇索引不是人为创建的&#xff0c;默认就有&#xff09;的时候&#xff0c;都会为这个索引创建一个 根节点 页面。最开始表中没有数据的时候&#xff0c;每个 B 树…...

前端面试话术集锦第 12 篇:高频考点(Vue常考基础知识点)

这是记录前端面试的话术集锦第十二篇博文——高频考点(Vue常考基础知识点),我会不断更新该博文。❗❗❗ 这一章节我们将来学习Vue的一些经常考到的基础知识点。 1. 生命周期钩子函数 在beforeCreate钩子函数调用的时候,是获取不到props或者data中的数据的,因为这些数据的…...

骨传导耳机危害有哪些?值得入手吗?

事实上&#xff0c;只要是正常使用&#xff0c;骨传导耳机并不会对身体造成伤害&#xff0c;并且在众多耳机种类中&#xff0c;骨传导耳机可以说是相对健康的一种耳机&#xff0c;这种耳机最独特的地方便是声波不经过外耳道和鼓膜&#xff0c; 而是直接将人体骨骼结构作为传声介…...

网络爬虫-----初识爬虫

目录 1. 什么是爬虫&#xff1f; 1.1 初识网络爬虫 1.1.1 百度新闻案例说明 1.1.2 网站排名&#xff08;访问权重pv&#xff09; 2. 爬虫的领域&#xff08;为什么学习爬虫 ?&#xff09; 2.1 数据的来源 2.2 爬虫等于黑客吗&#xff1f; 2.3 大数据和爬虫又有啥关系&…...

UNIGUI 修改网页图标 Delphi

网页图标delphi 软件上方工具栏Project -> Options -> Application -> Icons修改图标点击第一个LoadIcon按钮&#xff0c;然后选择一个你目标的.ioc格式大小是128*128的图标&#xff0c;点击 Save保存即可。服务器运行图标打开ServerModule页面&#xff0c;点击UniSer…...

AS3935闪电传感器Arduino驱动库深度解析与工业级应用

1. 项目概述AS3935 是一款由 AMS&#xff08;现为 ams OSRAM&#xff09;推出的专用闪电检测传感器芯片&#xff0c;集成 RF 前端、数字信号处理器&#xff08;DSP&#xff09;、闪电算法引擎及 IC/SPI 接口&#xff0c;可实现对 40 km 范围内云地闪&#xff08;CG&#xff09;…...

别再手动算置信区间了!ArcGIS里用Python脚本批量计算FVC,效率提升90%

遥感植被覆盖度自动化计算&#xff1a;用Python脚本解放ArcGIS生产力 当面对数百景遥感数据需要计算植被覆盖度(FVC)时&#xff0c;手动操作ArcGIS界面不仅耗时费力&#xff0c;还容易因人为失误导致结果不一致。我曾在一个省级生态评估项目中&#xff0c;需要处理3年共36期Lan…...

League Toolkit:重新定义英雄联盟游戏体验的智能辅助工具

League Toolkit&#xff1a;重新定义英雄联盟游戏体验的智能辅助工具 【免费下载链接】League-Toolkit 兴趣使然的、简单易用的英雄联盟工具集。支持战绩查询、自动秒选等功能。基于 LCU API。 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit 价值定位&am…...

StackEdit:让Markdown创作如虎添翼的开源编辑器全攻略

StackEdit&#xff1a;让Markdown创作如虎添翼的开源编辑器全攻略 【免费下载链接】stackedit In-browser Markdown editor 项目地址: https://gitcode.com/gh_mirrors/st/stackedit 1. 核心价值解析&#xff1a;为什么StackEdit能重塑你的写作体验&#xff1f; 想象一…...

STM32F1XX 的 CAN 的 波特率配置

参考文档&#xff1a; CAN总线波特率的设定——以STM32F103为例 - 知乎 42. CAN—通讯实验 — [野火]STM32库开发实战指南——基于野火霸道开发板 文档 基本知识 &#xff08;SMP 采样率&#xff09; STM32F1系列开发板设置的系统时钟大小 SYSCLK&#xff08;系统时钟&…...

Onekey:3分钟搞定Steam游戏清单下载的终极神器

Onekey&#xff1a;3分钟搞定Steam游戏清单下载的终极神器 【免费下载链接】Onekey Onekey Steam Depot Manifest Downloader 项目地址: https://gitcode.com/gh_mirrors/one/Onekey 还在为复杂的Steam游戏清单获取流程而烦恼吗&#xff1f;Onekey作为一款专业的Steam D…...

Logisim实战:从零到一构建MIPS32控制器核心模块

1. 初识MIPS32控制器设计 第一次接触MIPS32控制器设计时&#xff0c;我完全被那些密密麻麻的电路图和晦涩的指令格式搞懵了。记得当时在头歌平台上做实验&#xff0c;盯着Logisim界面整整半小时都不知道从何下手。后来才发现&#xff0c;理解控制器核心模块其实就像搭积木&…...

Windows 10下Cesium Terrain Builder编译踩坑实录(VS2015+GDAL环境配置)

Windows 10下Cesium Terrain Builder编译实战指南&#xff08;VS2015GDAL环境配置&#xff09; 在三维GIS开发领域&#xff0c;Cesium Terrain Builder&#xff08;CTB&#xff09;作为生成量化网格地形瓦片的核心工具&#xff0c;其编译过程却常让开发者望而生畏。特别是在Win…...

如何突破极域电子教室限制?3个高效学习工具推荐

如何突破极域电子教室限制&#xff1f;3个高效学习工具推荐 【免费下载链接】JiYuTrainer 极域电子教室防控制软件, StudenMain.exe 破解 项目地址: https://gitcode.com/gh_mirrors/ji/JiYuTrainer 在数字化教学环境中&#xff0c;极域电子教室作为常见的教学管理软件&…...