函数指针的重要用途——回调函数

什么是回调函数?

粗暴的说,如果一个函数作为另一个函数的参数传入,这种函数就可以称为回调函数(这句话并不严谨,但为了说明问题可以这么理解)。C语言里面,一般就是一个函数的参数列表中有函数指针,函数指针指向的函数就是一个回调函数。

为什么要有回调函数?

那为什么不直接在函数体内调用,而非要把函数指针作为参数呢?

举一个例子:系统提供一个排序函数sort(int a[ ]),排序函数默认升序,但如果我们想要降序排列呢?那系统还要提供一个降序版本?

显然,系统可以提供这样一个接口sort(int a[ ], void(p)(int) ),后者是一个指向排序方法的函数指针。用户可以自行定义排序方法。即,我们可以认为,回调函数有以下的功能:

  • 一个接口,可以实现不同的功能。这种思想不就是多态吗?本质上还是为了实现地址的晚绑定。C++中的仿函数,其实是对函数指针做了某种程度的简化,使用户使用更简单罢了,使用到的思想是一样的。
  • 通过回调函数可以修改一个黑盒子内部默认的功能,这也是业务上经常用的。

Linux操作系统用到了大量回调的思想,比如对于不同厂家提供的驱动,厂家按照Linux提供的接口标准编写自己的方法,而Linux接口的参数列表中就有指向对应方法的函数指针,这样尽管厂家不同,Linux也可以使用。

再举一个例子,默认情况下,当我们按下CTRL + C时,进程会终止。那我们想改变这样的默认行为怎么办,linux提供了signal这样一个接口。

 #include <signal.h>
  void (*signal(int sig, void (*func)(int)))(int);
</signal.h>

第一个参数是信号的编号,此处的ctrl + C对应的是2号信号,第二个参数就是一个函数指针,指向用户自己提供的方法。

如下面的这段代码:

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
void mysignal(int signo)
{
  printf("catch a signal! %d\n", signo);
}

int main()
{
  signal(2, mysignal);
  while(1)
  {
    printf("hello world!\n");
    sleep(1);
  }
  return 0;
}
</signal.h></unistd.h></stdio.h>

这段代码中,使用signal函数注册了一个新的方法,当按下ctrl + C时,不再默认终止进程,而是输出catch a signal! 2。效果如下:

函数指针的重要用途——回调函数

也就是说,系统提供接口用到了回调函数,用户定义该函数,实现了用户所需要的功能。这也是回调函数的主要应用方式。

Original: https://www.cnblogs.com/Grong/p/15642201.html
Author: 乌有先生ii
Title: 函数指针的重要用途——回调函数

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/585751/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 虚拟机的NAT网络配置

    写在前面: 本篇文章介绍如何使虚拟机使用VMware的NAT网络模式。NAT,即Network Address Translation的缩写,在NAT模式下虚拟机被接入到物理机的虚…

    Linux 2023年6月8日
    0135
  • 用shell抓取某考试试题

    一、背景 最近公司组织考信息安全,但考试机构没有整理出试题,只给了以下几个在线练习的链接,想着用博客整理下题库题型,奈何这个只能用拍照图片,然后用图片转文字的方式太慢,累死个人了,…

    Linux 2023年6月6日
    0106
  • Mysql数据库体系

    Mysql数据库体系如下(手绘): 描述: 1.DBMS:database system management是数据库管理软件,平时我们使用的数据库的全称,是C/S架构(clien…

    Linux 2023年6月14日
    0106
  • subprocess模块简介

    subprocess模块可以执行系统命令,该模块允许用户创建一个新的进程,该进程会连接到input|output|error管道并获取到返回的状态码。 本文版本是以python3….

    Linux 2023年6月7日
    082
  • 服务器部署 Vue 和 Django 项目的全记录

    本篇记录我在一个全新服务器上部署 Vue 和 Django 前后端项目的全过程,内容包括服务器初始配置、安装 Django 虚拟环境、python web 服务器 uWSGI 和反…

    Linux 2023年6月7日
    0119
  • 高速USB转4串口产品设计-TTL串口

    基于480Mbps 高速USB转8路串口芯片CH344Q,可以为各类主机扩展出4个独立的串口。CH344芯片支持使用操作系统内置的CDC串口驱动,也支持使用厂商提供的VCP串口驱动…

    Linux 2023年6月7日
    0110
  • Java8新特性终极指南

    欢迎来到Java学习之Java8新特性终极指南 目录 系列文章目录 @ 目录 系列文章目录 Java语言新特性 Lambda表达式 函数式接口 方法引用 接口的默认方法 重复注解 …

    Linux 2023年6月13日
    0115
  • find 查询命令 & 正则表达式

    今日内容 find 正则表达式 Linux 三剑客之 grep 内容详细 一、find 按名称或属性查询文件 按名称查询 find [查找目录] [参数] [] 通配符 : * 表…

    Linux 2023年5月27日
    0109
  • win7系统 右击任务栏 资源管理器 弹出菜单“已固定”和“最近”项目不显示故障处理

    故障描述:右击任务栏中资源管理器图标时,弹出菜单只有”资源管理器”和”解除锁定”两个项目,”已固定”和&#8…

    Linux 2023年6月8日
    0118
  • 【git】合并分支到主干master

    分支合并到master主干上 1.当前为其他分支切换到主分支上: git checkout [&#x4E3B;&#x5206;&#x652F;&#x…

    Linux 2023年6月13日
    0121
  • python爬虫_入门

    本来觉得没什么可写的,因为网上这玩意一搜一大把,不过爬虫毕竟是python的一个大亮点,不说说感觉对不起这玩意基础点来说,python2写爬虫重点需要两个模块,urllib和url…

    Linux 2023年6月6日
    091
  • 关于树莓派64位操作系统

    用过树莓派的都知道,在烧录操作系统时,官方只提供的32位的系统,这是官方经过测试和验证比较稳定的系统,对于使用4GB或8GB版本大内存树莓派用户来说,通常会将树莓派拿来充当服务器或…

    Linux 2023年5月27日
    0129
  • docker 常用批量操作

    显示所有镜像的tag docker images |awk ‘{print $1":"$2}’ 删除所有镜像 docker images |awk ‘{prin…

    Linux 2023年6月6日
    0106
  • 选择排序算法C语言实现

    选择排序C语言实现 int select_sort(int *list, int len) { int i = 0; int j = 0; int tmp = 0; int sma…

    Linux 2023年6月14日
    085
  • Densite_RANK 函数

    densite_RANK()是一个窗口函数,它为分区或结果集中的每一行分配一个等级,等级值之间没有间隔。 行的秩从行之前的不同秩值的数量增加1。 首先,PARTITION BY子句…

    Linux 2023年6月7日
    0101
  • 嵌入式软件架构设计-消息交互

    1、前言 在熟悉任务调度、程序分层和模块化编程关于软件架构、分层和模块设计后,除了函数调用设计中出现的情况外,还会遇到同层模块之前如何进行消息交互,通常是应用层之间。 比如一个设备…

    Linux 2023年6月7日
    0113
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球