当前位置: 首页 > 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 大数据和爬虫又有啥关系&…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)

说明&#xff1a; 想象一下&#xff0c;你正在用eNSP搭建一个虚拟的网络世界&#xff0c;里面有虚拟的路由器、交换机、电脑&#xff08;PC&#xff09;等等。这些设备都在你的电脑里面“运行”&#xff0c;它们之间可以互相通信&#xff0c;就像一个封闭的小王国。 但是&#…...

【WiFi帧结构】

文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成&#xff1a;MAC头部frame bodyFCS&#xff0c;其中MAC是固定格式的&#xff0c;frame body是可变长度。 MAC头部有frame control&#xff0c;duration&#xff0c;address1&#xff0c;address2&#xff0c;addre…...

PHP和Node.js哪个更爽?

先说结论&#xff0c;rust完胜。 php&#xff1a;laravel&#xff0c;swoole&#xff0c;webman&#xff0c;最开始在苏宁的时候写了几年php&#xff0c;当时觉得php真的是世界上最好的语言&#xff0c;因为当初活在舒适圈里&#xff0c;不愿意跳出来&#xff0c;就好比当初活在…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

(二)原型模式

原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

以光量子为例,详解量子获取方式

光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学&#xff08;silicon photonics&#xff09;的光波导&#xff08;optical waveguide&#xff09;芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中&#xff0c;光既是波又是粒子。光子本…...