C语言回调函数详解及实例

2023-11-08

C语言回调函数详解及实例

回调函数:函数 F1 调用函数 F2 的时候,函数 F1 通过参数给函数 F2 传递了另外一个函数 F3 的指针,在函数 F2 执行的过程中,函数F2 调用了函数 F3,这个动作就叫做回调(Callback),而先被当做指针传入、后面又被回调的函数 F3 就是回调函数。
F3作为客户函数,可由客户根据自己的需求任意编写。文后有回调函数的应用场景说明。

后期补充引例:

#include <stdio.h>
void F3()
{
	printf("F3()\n");
}
void F2(void(*callback)())
{
	printf("函数 F2() 中回调函数 F3()\n");

	//以下两种调用方式等价于直接使用
	//F3();

	callback();   //调用方式1
	(*callback)();//调用方式2
}
void F1()
{
	void (*pf)();
	printf("F1()\n");
	pf = F3;

	printf("----调用方式1----\n");
	F2(pf);

	printf("----调用方式2----\n");
	F2(F3);
}

int main()
{
	F1();
	return 0;
}

运行结果:
在这里插入图片描述

说明: 这篇文章是看了博客园大神的博客后觉得很有用,自己抄录以及整理了一些内容。其中 [标注] 以及 文章末尾 是自己的 理解与想法

致谢: 感谢原文博主的好文,帮助理解回调函数概念。
文章参考链接: https://www.cnblogs.com/jiangzhaowei/p/9129105.html.

1. 参考博文简化

1.什么是回调函数?

回调函数就是一个通过函数指针调用的函数。如果把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,就说这是回调函数。

可以将"回调函数"在字面上做个分解。中文其实可以理解为这么两种意思:1) 被回调的函数;2) 回头执行调用动作的函数。

回调:把一段可执行的代码像参数传递那样传给其他代码,而这段代码会在某个时刻被调用执行,这就叫做回调。如果代码立即被执行就称为同步回调,如果在之后晚点的某个时间再执行,则称之为异步回调。 [ 使用异步回调必须有 多线程或者有限状态机 机制 ]

2.为什么要使用回调函数?

很多朋友可能会想,为什么不像普通函数调用那样,在回调的地方直接写函数的名字呢?这样不也可以吗?为什么非得用回调函数呢?有这个想法很好,因为在网上看到解析回调函数的很多例子,其实完全可以用普通函数调用来实现的。要回答这个问题,我们先来了解一下回到函数的好处和作用,那就是解耦,对,就是这么简单的答案,就是因为这个特点,普通函数代替不了回调函数。所以,在我眼里,这才是回调函数最大的特点。来看看维基百科上面我觉得画得很好的一张图片。
在这里插入图片描述
下面以一段不完整的 C 语言代码来呈现上图的意思:

实例

#include<stdio.h>
#include<softwareLib.h> // 包含Library Function所在读得Software library库的头文件

int Callback() // Callback Function
{
    // TODO
    return 0;
}
int main() // Main program
{
    // TODO
    Library(Callback);
    // TODO
    return 0;
}

乍一看,回调似乎只是函数间的调用,和普通函数调用没啥区别,但仔细一看,可以发现两者之间的一个关键的不同: 在回调中,主程序把回调函数像参数一样传入库函数。这样一来,只要我们改变传进库函数的参数,就可以实现不同的功能,这样有没有觉得很灵活?并且丝毫不需要修改库函数的实现,这就是解耦。再仔细看看,主函数和回调函数是在同一层的,而库函数在另外一层,想一想,如果库函数对我们不可见,我们修改不了库函数的实现,也就是说不能通过修改库函数让库函数调用普通函数那样实现,那我们就只能通过传入不同的回调函数了,这也就是在日常工作中常见的情况。

现在再把main()、Library()和Callback()函数套回前面 F1、F2和F3函数里面,是不是就更明白了?
----------------------------------------------------------------------------实例-----------------------------------------------------------------------------

3. 怎么使用回调函数?

知道了什么是回调函数,了解了回调函数的特点,那么应该怎么使用回调函数?下面来看一段简单的可以执行的同步回调函数代码。

实例

#include<stdio.h>

int Callback_1() // Callback Function 1
{
    printf("Hello, this is Callback_1 ");
    return 0;
}

int Callback_2() // Callback Function 2
{
    printf("Hello, this is Callback_2 ");
    return 0;
}

int Callback_3() // Callback Function 3
{
    printf("Hello, this is Callback_3 ");
    return 0;
}

int Handle(int (*Callback)())
{
    printf("Entering Handle Function. ");
    Callback();
    printf("Leaving Handle Function. ");
}

int main()
{
    printf("Entering Main Function. ");
    Handle(Callback_1);
    Handle(Callback_2);
    Handle(Callback_3);
    printf("Leaving Main Function. ");
    return 0;
}

运行结果:

Entering Main Function.
Entering Handle Function.
Hello, this is Callback_1
Leaving Handle Function.
Entering Handle Function.
Hello, this is Callback_2
Leaving Handle Function.
Entering Handle Function.
Hello, this is Callback_3
Leaving Handle Function.
Leaving Main Function.

可以看到,Handle()函数里面的参数是一个指针,在main()函数里调用Handle()函数的时候,给它传入了函数Callback_1()/Callback_2()/Callback_3()的函数名,这时候的函数名就是对应函数的指针,也就是说,回调函数其实就是函数指针的一种用法。

4.怎么使用带参数的回调函数?
实例

#include<stdio.h>

int Callback_1(int x) // Callback Function 1
{
    printf("Hello, this is Callback_1: x = %d ", x);
    return 0;
}

int Callback_2(int x) // Callback Function 2
{
    printf("Hello, this is Callback_2: x = %d ", x);
    return 0;
}

int Callback_3(int x) // Callback Function 3
{
    printf("Hello, this is Callback_3: x = %d ", x);
    return 0;
}

int Handle(int y, int (*Callback)(int))
{
    printf("Entering Handle Function. ");
    Callback(y);
    printf("Leaving Handle Function. ");
}

int main()
{
    int a = 2;
    int b = 4;
    int c = 6;
    printf("Entering Main Function. ");
    Handle(a, Callback_1);
    Handle(b, Callback_2);
    Handle(c, Callback_3);
    printf("Leaving Main Function. ");
    return 0;
}

运行结果:

Entering Main Function.
Entering Handle Function.
Hello, this is Callback_1: x = 2
Leaving Handle Function.
Entering Handle Function.
Hello, this is Callback_2: x = 4
Leaving Handle Function.
Entering Handle Function.
Hello, this is Callback_3: x = 6
Leaving Handle Function.
Leaving Main Function.

可以看到,并不是直接把int Handle(int (*Callback)()) 改成 int Handle(int (*Callback)(int)) 就可以的,而是通过另外增加一个参数来保存回调函数的参数值,像这里 int Handle(int y, int (*Callback)(int)) 的参数 y。同理,可以使用多个参数的回调函数。

---------------------------------------------------------自己对回调函数的例子以及理解-----------------------------------------------------------
---------------------------------------------------------自己对回调函数的例子以及理解-----------------------------------------------------------

2. 回调函数的例子以及理解

1.理解示例

void 做面条(int x)//回调函数
{
    做x碗面条;
}
void 做米线(int x)//回调函数
{
    做x碗米线;
}
void 做蛋炒饭(int x)//回调函数
{
    做x碗蛋炒饭;
}
//吃饭函数里面内容不可见,只知道可以实现做几碗我需要的饭
viod 吃饭( int x, void (*做饭)(int) )
{
	摆桌子();//吃饭的公有功能函数
	做饭(x);
	洗碗();//吃饭的公有功能函数
}

void mian(void)
{
	吃饭(2,做米线);();
	睡觉();
}

2.本文理解

回调函数的意义在于,中间函数(库函数)的公有部分可以不必拆出来写到每一个子函数。
就上面例子来讲:对于吃饭来说操作流程都是一样的,没有必要全部把公有部分( 摆桌子()、洗碗() )单独拿出来写到3个不同的吃饭函数。也可以对应说是中间数吃饭()里面的内容对我们不可见,我们只能将具体做饭函数放入到中间函数去执行。

可能写的东西内容有所欠缺欠缺,望博友指正。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C语言回调函数详解及实例 的相关文章

  • 计算机基础:一颗芯片是怎样诞生的?

    一颗芯片是怎样诞生的 芯片属于半导体 半导体是介于导体和绝缘体之间的一类物质 元素周期表中硅 锗 硒 硼的单质都属于半导体 这些单质通过掺杂其他元素生成的一些化合物 也属于半导体的范畴 这些化合物在常温下可激发载流子的能力大增 导电能力大大
  • 华为OD机试真题-员工派遣-2023年OD统一考试(C卷)

    题目描述 某公司部门需要派遣员工去国外做项目 现在 代号为x的国家和代号为y的国家分别需要cntx名和cnty名员工 部门每个员工有一个员工号 1 2 3 工号连续 从1开始 部长派遣员工的规则 规则1 从 1 k 中选择员工派遣出去 规则
  • c 关于数组几个查序程序

    1 查询某元素是否在数组中 int main void char i 10 2 1 7 2 10 5 2 0 1 4 10 10 1 3 1 0 8 char z 10 1 2 3 4 1 4 6 8 0 9 int zz 0 标志位 0
  • C语言入门引导

    第一章 概述 第一节 引例 第二节 C语言的基本字符与关键字 第三节 算法及其表示 第二章 数据类型 运算符与表达式 第一节 C语言的数据类型 第二节 常量与变量 第三节 运算符与表达式 第四节 数据类型转换 第三章 顺序结构与程序设计 第
  • 华为OD机试真题-分配土地-2023年OD统一考试(C卷)

    题目描述 从前有个村庄 村民们喜欢在各种田地上插上小旗子 旗子上标识了各种不同的数字 某天集体村民决定将覆盖相同数字的最小矩阵形的土地的分配给为村里做出巨大贡献的村民 请问 此次分配土地 做出贡献的村民中最大会分配多大面积 输入描述 第一行
  • 【华为OD机考 统一考试机试C卷】高效货运(C++ Java JavaScript Python)

    华为OD机考 统一考试 C卷 D卷 B卷 A卷 2023年11月份 华为官方已经将 华为OD机考 OD统一考试 A卷 B卷 切换到 OD统一考试 C卷 和 OD统一考试 D卷 根据考友反馈 目前抽到的试卷为B卷或C卷 D卷 其中C卷居多 按
  • [补题记录] Educational Codeforces Round 160 (Rated for Div. 2)(A~C)

    URL https codeforces com contest 1913 problem D 目录 A Problem 题意 Thought 思路 Code 代码 B Problem 题意 Thought 思路 Code 代码 C Pro
  • c语言:指针作为参数传递

    探究实参与形参它们相互独立 由于主调函数的变量 a b 与被调函数的形参 x y 它们相互独立 函数 swap 可以修改变量 x y 但是却无法影响到主调函数中的 a b 现在利用取地址运算符 分别打印它们的首地址 让我们从内存的角度 来分
  • 华为OD机试真题-螺旋数字矩阵-2023年OD统一考试(C卷)

    题目描述 疫情期间 小明隔离在家 百无聊赖 在纸上写数字玩 他发明了一种写法 给出数字 个数n 和 行数m 0 lt n 999 0 lt m 999 从左上角的1开始 按照 顺时针螺旋向内写 方式 依次写出2 3 n 最终形成一个 m行矩
  • C/C++编程:令人印象深刻的高级技巧案例

    C C 编程语言在软件开发领域有着悠久的历史 由于其高效 灵活和底层访问能力 至今仍然被广泛应用 本文将介绍一些在C C 编程中令人印象深刻的高级技巧 帮助读者提升编程水平 更加高效地使用这两种强大的编程语言 一 指针运算与内存管理 C C
  • [补题记录] Educational Codeforces Round 160 (Rated for Div. 2)(A~C)

    URL https codeforces com contest 1913 problem D 目录 A Problem 题意 Thought 思路 Code 代码 B Problem 题意 Thought 思路 Code 代码 C Pro
  • C 库函数 - gmtime()

    描述 C 库函数 struct tm gmtime const time t timer 使用 timer 的值来填充 tm 结构 并用协调世界时 UTC 也被称为格林尼治标准时间 GMT 表示 声明 下面是 gmtime 函数的声明 st
  • linux 内核同步互斥技术之cache 伪共享和隐含内存屏障

    隐含内存屏障 内核的有些函数隐含内存屏障 1 获取和释放函数 2 中断禁止函数 1 获取和释放函数 获取 acquire 函数包括如下 1 获取锁的函数 锁包括自旋锁 读写自旋锁 互斥锁 信号量和读写信号量 2 smp load acqui
  • 华为OD机试真题-部门人力分配-2023年OD统一考试(C卷)

    题目描述 部门在进行需求开发时需要进行人力安排 当前部门需要完成N个需求 需求用requirements 表示 requirements i 表示第i个需求的工作量大小 单位 人月 这部分需求需要在M个月内完成开发 进行人力安排后每个月的人
  • 《妙趣横生的算法》(C语言实现)- 第6章 数学趣题(二)

    6 1 连续整数固定和问题 找出任意输入的整数n的全部的连续整数固定和 题目分析 至少要找出两个连续整数的固定和 一个整数的话就是本身了呢 那如何确定这些连续整数呢 想明白了 第一个整数设为a 第二个整数是a 1 假设有m个连续整数 那么第
  • linux 内核同步互斥技术之cache 伪共享和隐含内存屏障

    隐含内存屏障 内核的有些函数隐含内存屏障 1 获取和释放函数 2 中断禁止函数 1 获取和释放函数 获取 acquire 函数包括如下 1 获取锁的函数 锁包括自旋锁 读写自旋锁 互斥锁 信号量和读写信号量 2 smp load acqui
  • 牛客字符串

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 前言 一 pandas是什么 二 使用步骤 1 引入库 2 读入数据 总结 前言 提示 这里可以添加本文要记录的大概内容 例如 随着人工智能的不断发展 机器学习这门
  • C和指针课后答案

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 前言 一 pandas是什么 二 使用步骤 1 引入库 2 读入数据 总结 前言 第八章课后答案 提示 以下是本篇文章正文内容 下面案例可供参考
  • 华为OD机试真题-整数对最小和-Java-OD统一考试(C卷)

    题目描述 给定两个整数数组array1 array2 数组元素按升序排列 假设从array1 array2中分别取出一个元素可构成一对元素 现在需要取出k对元素 并对取出的所有元素求和 计算和的最小值 注意 两对元素如果对应于array1
  • 用栈实现队列(OJ中报错的处理)

    用栈实现队列 ERROR AddressSanitizer myQueueFree函数中栈的释放处现了问题 没有调用StackDestory而是直接free了 这个是栈初始化时 capacity与malloc申请的空间大小没有匹配 请你仅使

随机推荐