原标题:关于C语言回调函数的详解~

01

什么是回调函数?

回调函数,光听名字就比普通函数要高大上一些,那到底什么是回调函数呢?恕我读得书少,没有在那本书上看到关于回调函数的定义。我在百度上搜了一下,发现众说纷纭,有很大一部分都是使用类似这么一个场景来说明:A君去B君店里买东西,恰好缺货,A君留下号码给B君,有货时通知A君。感觉这个让人更容易想到的是异步操作,而不是回调。另外还有两句英文让我印象深刻:

1) If you call me, I will call you back;

2) Don't call me, I will call you.

看起来好像很有道理,但是仔细一想,普通函数不也可以做到这两点吗?所以,我觉得这样的说法都不是很妥当,因为我觉得这些说法都没有把回调函数的特点表达出来,也就是都看不到和普通函数到底有什么差别。不过,百度百科的解析我觉得还算不错(虽然经常吐槽百度搜索...):回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。

下面先说说我的看法。我们可以先在字面上先做个分解,对于"回调函数",中文其实可以理解为这么两种意思:

1) 被回调的函数;

2) 回头执行调用动作的函数。那这个回头调用又是什么鬼?

先来看看来自维基百科的对回调(Callback)的解析:In computer programming, a callback is any executable code that is passed as an argument to other code, which is expected to call back (execute) the argument at a given time. This execution may be immediate as in a synchronous callback, or it might happen at a later time as in an asynchronous callback. 也就是说,把一段可执行的代码像参数传递那样传给其他代码,而这段代码会在某个时刻被调用执行,这就叫做回调。如果代码立即被执行就称为同步回调,如果在之后晚点的某个时间再执行,则称之为异步回调。关于同步和异步,这里不作讨论,请查阅相关资料。

再来看看来自Stack Overflow某位大神简洁明了的表述:A "callback" is any function that is called by another function which takes the first function as a parameter。也就是说,函数 F1 调用函数 F2 的时候,函数 F1 通过参数给 函数 F2 传递了另外一个函数 F3 的指针,在函数 F2 执行的过程中,函数F2 调用了函数 F3,这个动作就叫做回调(Callback),而先被当做指针传入、后面又被回调的函数 F3 就是回调函数。到此应该明白回调函数的定义了吧?

02

为什么要使用回调函数?

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

下面以一段不完整的 C 语言代码来呈现上图的意思:

# include

# include // 包含Library Function所在读得Software library库的头文件

intCallback// Callback Function{// TODOreturn0;}intmain// Main program{// TODOLibrary(Callback);// TODOreturn0;}

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

明白了回调函数的特点,是不是也可以大概知道它应该在什么情况下使用了?没错,你可以在很多地方使用回调函数来代替普通的函数调用,但是在我看来,如果需要降低耦合度的时候,更应该使用回调函数。

03

怎么使用回调函数?

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

# includeintCallback_1// Callback Function 1{printf( "Hello, this is Callback_1 ");return0;}

intCallback_2// Callback Function 2{printf( "Hello, this is Callback_2 ");return0;}

intCallback_3// Callback Function 3{printf( "Hello, this is Callback_3 ");return0;}

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

intmain{printf( "Entering Main Function. ");Handle(Callback_1);Handle(Callback_2);Handle(Callback_3);printf( "Leaving Main Function. ");return0;}

运行结果:

可以看到,Handle函数里面的参数是一个指针,在main函数里调用Handle函数的时候,给它传入了函数Callback_1/Callback_2/Callback_3的函数名,这时候的函数名就是对应函数的指针,也就是说,回调函数其实就是函数指针的一种用法。现在再读一遍这句话:A "callback" is any function that is called by another function which takes the first function as a parameter,是不是就更明白了呢?

04

怎么使用带参数的回调函数?

眼尖的朋友可能发现了,前面的例子里面回调函数是没有参数的,那么我们能不能回调那些带参数的函数呢?答案是肯定的。那么怎么调用呢?我们稍微修改一下上面的例子就可以了:

# includeintCallback_1( intx)// Callback Function 1{printf( "Hello, this is Callback_1: x = %d ", x);return0;}

intCallback_2( intx)// Callback Function 2{printf( "Hello, this is Callback_2: x = %d ", x);return0;}

intCallback_3( intx)// Callback Function 3{printf( "Hello, this is Callback_3: x = %d ", x);return0;}

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

intmain{inta = 2;intb = 4;intc = 6;printf( "Entering Main Function. ");Handle(a, Callback_1);Handle(b, Callback_2);Handle(c, Callback_3);printf( "Leaving Main Function. ");return0;}

运行结果:

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

免责声明:本文系网络转载,版权归原作者所有。如涉及作品版权问题,请与我们联系,我们将根据您提供的版权证明材料确认版权并支付稿酬或者删除内容。返回搜狐,查看更多

责任编辑:

c语言 is函数,关于C语言回调函数的详解~相关推荐

  1. c语言回调函数_C语言学习第26篇---函数与指针分析 回调函数

    函数类型的概念 1.C语言函数也是有类型的 2.函数类型由函数返回值,参数类型,参数个数共同决定 int add(int i,int j) 的类型是 int(int , int) 3.C语言中通过ty ...

  2. C语言、嵌入式重点知识:回调函数

    前言 上文分享了一个专用的双链表的基本操作示例:双链表的操作示例(附代码) 这里提到了一个关键词:专用.与专用对应的词是通用. 我们从字面上可以很容易理解这两个词,专用就是针对特定情况的,特点就是很有 ...

  3. C语言 函数指针做函数参数(即回调函数)

    文章目录 函数指针做函数参数(回调函数) 回调函数概念 一般有三种调用方式 回调函数的作用 回调函数调用时刻 回调函数的语法: 1.简单的函数类型为:无参数.无返回值的函数. 2.完全形式的回调函数 ...

  4. C语言基础10——指针进阶。字符指针、指针数组、数组指针、函数指针、函数指针数组、回调函数、数组名详解、杨氏矩阵、字符串旋转

    目录 字符指针 指针数组 数组指针 数组传参.指针参数 函数指针 函数指针数组 指向函数指针数组的指针 回调函数 练习 数组名的意义 指针笔试题 字符指针 字符指针的另一种使用方式 #include ...

  5. 回调函数举例ajax,通过回调函数的理解来进一步理解ajax及其注意的用法

    一,再一次理解回调函数 (function($){ $.fn.shadow = function(opts){ //定义的默认的参数 var defaults = { copies: 5, opaci ...

  6. 什么是回调函数?为什么要使用回调函数?如何使用回调函数?

    1. 什么是回调函数: 函数指针的调用,即是一个通过函数指针调用的函数: 如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,就说这是回调函数. In compu ...

  7. 电大计算机C语言1253,1253《C语言程序设计》电大期末精彩试题及其问题详解

    1253<C语言程序设计>电大期末精彩试题及其问题详解 (34页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 19.90 积分 实用文档&l ...

  8. 【Android 高性能音频】AAudio 音频流 PCM 采样 的 采样 缓冲 播放 的 连续机制 ( 数据回调机制 | 数据回调函数指针 | 实现数据回调函数 | 设置数据回调函数 )

    文章目录 I . AAudio 音频流 采样 缓冲 播放 的连续机制 II . AAudio 音频流 数据回调函数 函数指针类型定义 III . AAudio 音频流 数据回调函数 实现 IV . A ...

  9. js中函数的参数为函数的情况即回调函数

    js中函数的参数可以是数组对象也可以是函数,当参数为函数时我们叫做回调函数 //定义回调函数 function B() { console.log("函数B") setTimeou ...

  10. js中的回调函数,什么是回调函数?

    一. 回调函数的作用 js代码会至上而下一条线执行下去,但是有时候我们需要等到一个操作结束之后再进行下一个操作,这时候就需要用到回调函数. 二. 回调函数的解释 因为函数实际上是一种对象,即是内置对象 ...

最新文章

  1. Android程序员眼中世界上最遥远的距离
  2. node-mongoDB
  3. Spring(四)Bean注入方试
  4. 最小安装虚拟机命令行安装图形化
  5. Centos7系统、Hadoop集群上部署ntp服务器
  6. Lighting System Design UVA - 11400 动态规划
  7. SQL提取时间段内数据
  8. 基础知识(四)Dijkstra算法
  9. Java中json格式的字符串数组,list,json,map相互转换
  10. modify sql_在SQL Server中使用JSON_MODIFY()修改JSON数据
  11. quatus ii------调试利器 SignalTap II简介(基于TIGER BOARD 板子)
  12. “如何学习”系列文章2007年全部文章索引
  13. php sns 源码,ThinkSNS V2.3源码下载(SNS系统)
  14. 计算机培训短期速成班,【电脑基础班、速成班、短期班、计算机一级培训班】价格,厂家,电子商务-搜了网...
  15. 小米路由器r2d_小米路由器R2D固件下载
  16. java中n次方怎么表示_java中的一个数的N次方
  17. win10检测不到第二个显示器怎么解决 win10外接显示器黑屏怎么办
  18. Fernando Torres
  19. 基于JavaWeb的小区物业管理系统的设计与实现
  20. 【Python成长之路】快速理解复制、浅拷贝、深拷贝

热门文章

  1. 如何让vim编辑器永久显示行号
  2. 统计查询和组合查询(SQL SERVER 2008)
  3. LaTex使用技巧11:解决段落首行不缩进
  4. 自动解压缩pcap中chunk编码和gzip压缩的数据
  5. ShellShock(破壳漏洞)的简单分析
  6. Cannot add property xxx, object is not extensible
  7. grid布局浏览器兼容_grid布局适配IE
  8. 计算机绘图1091大作业,2018秋季【西南大学】[1091]《计算机绘图(1)》作业(参考答案)...
  9. FTP暴力破解-Hydra
  10. CSRF攻击实验 ——合天网安实验室学习笔记