C:回调函数的介绍-学习笔记

news2024/9/25 21:26:13

前言:

本篇文章我们将继续指针相关知识:回调函数

希望大家在看完后能够有所收获!

回调函数

 定义与概念

回调函数是一个通过指针调用的函数。

如果把函数指针作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,被调用的函数就是回调函数,回调函数不是有该函数的实现方直接调用,而是在特定的时间或条件发生时有另外的一方调用的,用于对该事件或条件进行响应。

假设有一个函数 A,它接收另一个函数 B 作为参数。当函数 A 在执行过程中达到某个特定条件时,它就会调用函数 B。这里的函数 B 就是回调函数。

是不是有点难以理解?我们先举个简单的实例来解释一下概念。

在该代码中,我们将add函数地址当作参数传递给test函数,然后通过函数指针pf找到add函数完成运算,在这个过程中,add函数就是回调函数。

 典型例题

我们来使用回调函数简化编写计算器程序的代码

简化前:

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;
}
#include <stdio.h>
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("请输入两个操作数:");
			scanf("%d %d", &x, &y);
			ret = Add(x, y);
			printf("%d\n", ret);
			break;
		case 2:
			printf("请输入两个操作数");
			scanf("%d %d", &x, &y);
			ret = Sub(x, y);
			printf("%d\n", ret);
			break;
		case 3:
			printf("请输入两个操作数");
			scanf("%d %d", &x, &y);
			ret = Mul(x, y);
			printf("%d\n", ret);
			break;
		case 4:
			printf("请输入两个操作数");
			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;
}

通过上面的代码,我们能够完成计算器的基本功能实现,但是我们可以看到有大量的重复代码,导致代码冗余,怎么解决呢?在不使用回调函数的情况下。

我们是否可以尝试将相同的代码提出来?

这样看起来似乎完成了简化代码的操作,我们来测试一下、

可以发现,就算我们选择错误,也会让我们先输入两个操作数,这样在逻辑上就出现了问题,所以这样将相同的代码提出来的方法不可行。

那这里我们应该做呢?如何使用回调函数呢?

简化后:

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;
}
calc(int(*pf)(int, int))
{
	int x = 0;
	int y = 0;
	int ret = 0;
	printf("请输入两个操作数:");
	scanf("%d %d", &x, &y);
	ret = pf(x, y);
	printf("%d\n", ret);
}
#include <stdio.h>
int main()
{
	int input = 0;
	
	do
	{
		menu();
		printf("请选择:");
		scanf("%d", &input);
		
		switch (input)
		{
		case 1:		
			calc(Add);//将加法函数
			break;
		case 2:	
			calc(Sub);
			break;
		case 3:
			calc(Mul);
			break;
		case 4:
			calc(Div);
			
			break;
		case 0:
			printf("退出计算器\n");
			break;	
		default:
			printf("选择错误,请重新选择\n");
			break;
		}
		
	} while (input);
	return 0;
}

在上面代码中的calc函数,具有通用功能,可以计算 + - * / 四种运算,它通过接收传递过来的函数地址,来找到对应的函数,比如说将Add函数地址传递给calc函数,然后calc函数再通过函数指针pf找到函数Add完成加法运算。

 回调函数的作用

1.回调函数能够提高代码的复用性

  • calc函数可以被不同的运算函数调用,实现了代码的复用。无论是什么运算,只要符合函数指针的类型要求,都可以作为回调函数传递给calc进行运算。
  • 例如,如果在其他地方也需要进行类似的运算操作,可以直接调用calc函数,并传入相应的回调函数,而不需要重复编写输入处理和结果输出的代码。

2.回调函数的使用可以使得整个工程中有清晰的代码结构

  • menu函数负责展示菜单和接收用户输入,switch 语句根据用户输入决定调用哪个运算函数作为回调。而calc函数则专注于执行具体的运算操作,它并不关心具体的运算是什么,只需要接收一个函数指针作为参数,然后调用这个函数指针指向的回调函数进行运算。
  • 这种分离使得代码结构更加清晰,各个部分的职责明确,易于理解和修改。

结语:

本篇文章主要讲了回调函数的一些基本概念和例题介绍,后面随着小编学习的深入,会不断更新该模块的更多知识。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2077607.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ARM32开发——(十四)GD32F4_DMA功能查询

GD32F4系列微控制器支持DMA&#xff08;Direct Memory Access&#xff09;功能&#xff0c;该功能允许外设通过DMA控制器直接访问内存&#xff0c;从而减轻CPU的负担。GD32F4系列微控制器的DMA功能如下&#xff1a; 支持最多8个DMA通道&#xff0c;每个通道都可以对应一个外设…

MySQL集群技术2——MySQL的主从复制

MySQL主从复制 MySQL 主从复制是一种常用的数据复制机制&#xff0c;它允许在一个或多个从属服务器上复制来自主服务器的数据更改。这种机制对于实现数据备份、负载均衡、读写分离等多种应用场景都非常有用。下面是关于 MySQL 主从复制的详细说明&#xff1a; MySQL 主从复制…

Linux平台下UE的代码启动流程

文章目录 概述main(主函数)CommonUnixMain(unix平台通用函数)GuardedMain(引擎主函数)AppExitCallback(退出调用) 小结 概述 本篇主要写下Linux下UE的启动流程&#xff0c;主要还是代码流程。从最开始的main函数&#xff0c;到最后的引擎层的启动退出&#xff0c;至于中间加载…

显示器熄屏待机时,音响持续发出USB插入和拔出的声音的解决方法!

电脑电源计划设置经过一段时间自动关闭显示屏&#xff0c;当显示屏关闭的时候&#xff0c;连接电脑主机的音响会每隔大约5秒左右持续播放USB插入和拔出的提示声&#xff0c;非常烦人。 网上搜索的解决方法是在显示器的设置中将输入源的【自动输入】关闭即可。原因是显示器信号被…

从汇编层看64位程序运行——C++的Copy Elision(复制省略)技术的实现

大纲 Copy Elision的应用场景返回值优化&#xff08;Return Value Optimization, RVO&#xff09;命名返回值优化&#xff08;Named Return Value Optimization, NRVO&#xff09;C11及以后的移动语义 禁用Copy Elision&#xff08;复制省略&#xff09;Copy Elision&#xff0…

Redis 的 主从复制

目录 1 Redis 主从复制介绍 2 Redis主从复制原理 2.1 主从同步过程 3 Redis实现主从复制 3.1 环境配置 3.2 修改各节点的配置文件 3.2.1 MASTER 3.2.2 SLAVE 3.3.3 重启Redis 3.3 查看是否实现了主从复制 3.3.1 MASTER 3.3.2 SLAVE 3.3.3 Redis 常用操作 3.3.4 数据添加查看…

AD9162数据链路lanes与FPGA高速BANK引脚交叉相连导致vivado编译失败

问题概述 对AD9162芯片进行功能开发时&#xff0c;发现AD9162的链路lanes与FPGA的高速BANK引脚存在交叉相连的情况&#xff0c;按照实际的引脚连接关系进行约束后&#xff0c;vivado编译失败。 问题阐述及原因分析 问题详情阐述 板卡对AD9162芯片进行功能开发时&#xff0c;发…

高并发业务下的库存扣减技术方案设计

扣减库存需要查询库存是否足够: 足够就占用库存不够则返回库存不足&#xff08;这里不区分库存可用、占用、已消耗等状态&#xff0c;统一成扣减库存数量&#xff0c;简化场景&#xff09; 并发场景&#xff0c;若 查询库存和扣减库存不具备原子性&#xff0c;就可能超卖&…

node.js使用express框架实现api接口开发(从零开始,超简单可直接复制)

目录 一、效果图 二、实现 1、引入express框架依赖 2、 新建启动文件&#xff08;/server/index.js&#xff09; 3、新建接口函数文件&#xff08;/server/router.js&#xff09; 一、效果图 二、实现 1、引入express框架依赖 在项目文件夹根目录下&#xff0c;打开控制台…

ShenNiusModularity:一款基于 .NET Core 框架研发的自媒体内容管理系统

项目介绍 ShenNiusModularity是一款基于 .NET Core 框架研发的、开源、免费的自媒体内容管理系统。项目秉承大道至简的原则开发&#xff0c;坚持业务模块最低复杂度复用&#xff0c;代码方面追求简单、高效、实用。适合小白入门进阶&#xff0c;同样适用老手上路干活。 项目包…

Python青少年简明教程:字符串

Python青少年简明教程&#xff1a;字符串 字符串&#xff08;string&#xff09;是用于表示文本的数据类型。它是不可变的序列类型&#xff0c;即一旦创建&#xff0c;字符串中的字符就无法改变。 下面对Python中字符串的详细介绍&#xff0c;包括字符串的创建、操作和常见方法…

MySQL 集群技术全攻略:从搭建到优化(下)

目录 四.mysql高可用之组复制 (MGR) 1.组复制流程 2.组复制单主和多主模式 3.实现mysql组复制 五.mysql-router&#xff08;mysql路由&#xff09; 1.Mysql route的部署方式 六.mysql高可用之MHA 1.MHA架构图 2.为什么要用MHA&#xff1f; 3.MHA 的组成 4.什么是 MH…

网络 (tcp)

客户端 /*************************************************************************> File Name: client.c> Author: yas> Mail: rage_yashotmail.com> Created Time: Thu 22 Aug 2024 04:04:26 PM CST******************************************************…

从零开始学习SLAM六(单应矩阵)

本文参考&#xff1a;计算机视觉life 概念 单应性&#xff08;homography&#xff09;是指两个平面之间的一种保直线性的对应关系。如果一个平面上的点集经过某种变换后&#xff0c;在另一个平面上形成的新点集仍然保持原来的线性特性&#xff08;如共线的点仍然共线&#xf…

一起搭WPF界面之View的简单设计一

一起搭WPF界面之View的简单设计一 1 前言2 界面预期设想3 基础的实现步骤3.1 界面划分3.1.1 基础框架代码&#xff1a;3.1.2 实现效果 4 界面花样设计4.1 花样设计4.2 界面源代码4.3 错误提醒4.3.1 错误14.3.2 错误2 总结 1 前言 基于上一篇的window、Gird、Border的简单介绍&…

XSS LABS - Level 13 过关思路

关注这个靶场的其他相关笔记&#xff1a;XSS - LABS —— 靶场笔记合集-CSDN博客 0x01&#xff1a;过关流程 进入靶场&#xff0c;老样子&#xff0c;右击&#xff0c;查看页面源码&#xff0c;找找不同&#xff1a; 可以看到&#xff0c;本关又多了一个新字段 t_cook&#xf…

关于 Vue/React 的 cli 中运用 webpack 打包的原理简单解析

webpack、webpack-cli的打包 关于 webpack 对前端工程中进行资源文件进行打包处理的过程中&#xff0c;运用到的核心插件主要是 webpack 和 webpack-cli&#xff0c;在 react 和 vue 对于打包各自工程中的 cli 则是进行了自定义的构建&#xff0c;专门用于项目打包的 …

【MySQL-25】万字总结<锁>——(全局锁&行级锁&表级锁)【共享锁,排他锁】【间隙锁,临键锁】【表锁,元数据锁,意向锁】

前言 大家好吖&#xff0c;欢迎来到 YY 滴MySQL系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY的《Lin…

Bytebase 2.22.2 - 允许在工作空间为群组分配角色

&#x1f680; 新功能 允许在工作空间给群组分配角色。 支持禁用邮箱密码登录&#xff0c;仅允许 SSO 登录的设置项。 新增 Postgres SQL 审核规则&#xff1a;禁止在列上设置会变化的默认值。 &#x1f514; 重大变更 下线项目内的变更历史页面&#xff1b;所有变更历史仍可…

Phoenix

Apache Phoenix 是一个开源的关系数据库层&#xff0c;运行在 Apache HBase 之上&#xff0c;旨在为 HBase 提供 SQL 查询能力和优化的存储引擎。它允许用户使用标准的 SQL 查询和事务语义来管理 HBase 中的数据&#xff0c;并且可以与现有的大数据生态系统无缝集成。Phoenix 通…