【 C 】回调函数简记

举报
李锐博恩 发表于 2021/07/15 08:31:54 2021/07/15
【摘要】 最近心特别浮躁,还没到晚上十点,就安定不下来了,但是这篇博文还必须记完! 上篇博文:函数指针,对这篇博文的理解也比较重要。 《c 与 指针》对于回调函数讲的也比较细致了,耐心看完,也会收获颇多,学习完毕,我简单地记录下吧: 以一个案例引入主题: 下面是一个在单链表中查找一个值的简单的函数。它的参数是一个指向链表第一个节点的指针以及那个需要查找的值。 Node *se...

最近心特别浮躁,还没到晚上十点,就安定不下来了,但是这篇博文还必须记完!

上篇博文:函数指针,对这篇博文的理解也比较重要。

《c 与 指针》对于回调函数讲的也比较细致了,耐心看完,也会收获颇多,学习完毕,我简单地记录下吧:

以一个案例引入主题:

下面是一个在单链表中查找一个值的简单的函数。它的参数是一个指向链表第一个节点的指针以及那个需要查找的值。


      Node *search_list( Node *node, int const value )
      {
      while( node != NULL )
       {
      if( node->value == value )
      break;
       node = node->link;
       }
      return node;
      }
  
 

这个函数特别简单,所以让人感觉到很亲切,至少对于我这种菜鸟来说,是亲切感爆棚。

可是呢?现实很残忍,我们必须开发出功能更加强大的查找链表中值的函数,不光是链表,其他领域也行。

怎么个强大法呢?在这里具体而言,就是上述函数只能处理这样的单链表——链表中的值为整数。我们想要一个这样的函数,它可以处理各种类型的值,例如我可以在一个字符串链表中查找!

我们就想一个通用的方法来使得查找函数与类型无关,这样它就能用于任何类型的值的链表。

这是我们就用到了回调函数这样一个概念。

就在上述函数的基础上修改吧。我们必须对函数两个方便进行修改:

第一个方面是,我们必须改变比较的执行方式,使函数可以对任何类型的值进行比较。如何实现,就是使用函数指针来间接访问一个比较函数,(由这个比较函数代替上述代码中的 ==),这个比较函数由你自己定义,这样就比较自由了,下面我们定义一个比较函数看看:


      int compare_ints( void const *a, void const *b )
      {
      if( *(int *)a == *(int *)b )
      return 0;
      else
      return 1;
      }
  
 

这个比较函数是对整型值进行比较的,如果对其他类型的值进行比较,只需要改变强制类型转换的类型就可以了。注意,也要把函数名也改下,要不然,暗示作用太强。

这个函数的使用在这里是用一个指向该函数的指针作为参数传递给查找函数。然后查找函数调用这个函数来执行值的比较。使用这种方法,任何类型的值都可以进行比较。

必须修改的第2个方面是向函数传递一个指向值的指针而不是值本身。函数有一个void * 形参,用于接收这个参数。然后指向这个值的指针便传递给比较函数。

使用这个技巧的函数称为回调函数(callback function),因为用户把一个函数指针(指向比较函数的指针)作为参数传递给其他函数(查找函数),后者(查找函数)将“回调”用户的函数(比较函数)。任何时候,如果你所编写的函数必须能够在不同的时刻执行不同类型的工作或者执行只能由函数调用者定义的工作,你都可以使用这个技巧。

我们无法在这个上下文环境中为回调函数编写一个准确的原型,因为我们并不知道进行比较的值的类型。事实上,我们需要查找函数能作用于任何类型的值。解决这个难题的方法是把参数类型声明为 void *,表示一个“指向未知类型的指针”。

下面是与类型无关的链表查找函数:


      #include <stdio.h>
      #include "node.h"
      Node *search_list( Node *node, void const *value,
      int (*compare)( void const *, void const * ) )
      {
      while( node != NULL )
       {
      if( compare( &node->value, value ) == 0 )
      break;
       node = node->link;
       }
      return node;
      }
  
 

最后讲讲这个函数是如何被调用的:

desired_node = search_list(root, &desired_value, compare_ints );

这个调用用来查找整型链表中的某个节点的值。

如果希望在一个字符串链表中进行查找呢?


      #include <string.h>
      ...
      desired_node = search_list(root, "desired_value", strcmp );
  
 

碰巧,库函数strcmp所执行的比较和我们需要的一样,不过编译器会发出警告,因为它的参数被声明为char *而不是 void *。

不过没关系,如果你需要比较字符串的话,确实传递进去的参数就是char *,且void *可以转换为任何其他类型的指针。

文章来源: reborn.blog.csdn.net,作者:李锐博恩,版权归原作者所有,如需转载,请联系作者。

原文链接:reborn.blog.csdn.net/article/details/82695410

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。