V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
silver107
V2EX  ›  问与答

什么是回调函数( C 语言)?

  •  
  •   silver107 · 2015-08-25 23:47:09 +08:00 · 2566 次点击
    这是一个创建于 3379 天前的主题,其中的信息可能已经有所发展或是发生改变。

    “你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货。在这个例子里,你的电话号码就叫回调函数,你把电话留给店员就叫登记回调函数,店里后来有货了叫做触发了回调关联的事件,店员给你打电话叫做调用回调函数,你到店里去取货叫做响应回调事件。( by 常溪玲)”

    目前处于似懂非懂状态,谁可以帮忙用实例( C 语言)来解析一下怎样是登记回调函数、触发了回调关联的事件、调用回调函数、响应回调事件。

    第 1 条附言  ·  2015-08-26 00:23:12 +08:00
    我比较想明确的指出哪一句是登记回调函数、
    哪一句是触发了回调关联的事件、
    哪一句是调用回调函数、
    哪一句是响应回调事件。
    11 条回复    2015-08-26 10:07:02 +08:00
    ljbha007
        1
    ljbha007  
       2015-08-26 00:07:34 +08:00   ❤️ 1
    https://gist.github.com/CarlLee/bef2ded975b24303ba1e

    其实说白了就是程序的不同部分之间 用一种事前约定好的形式(一般是一个约定好参数和返回值的函数)

    让其中一段程序的编写者不需要知道另一段程序的具体代码的情况下可以通过约定好的协议 在另一段代码某个关键时刻执行自己想要的代码 从而部分控制另一端代码的行为 让程序的不同组建之间可以灵活的通信却不需要每个人都把所有代码读完
    Andiry
        2
    Andiry  
       2015-08-26 00:12:30 +08:00
    中断函数就是一种回调函数, epoll 也是用回调实现的。
    http://freehui.com/?post=27
    fo2w
        3
    fo2w  
       2015-08-26 00:12:37 +08:00   ❤️ 1
    先生, 您要的薯条我们还在炸
    您拿着这号
    炸好我们叫您
    silver107
        4
    silver107  
    OP
       2015-08-26 00:27:46 +08:00
    @ljbha007 隐约明白。希望能指出哪里是登记(或注册)回调函数
    silver107
        5
    silver107  
    OP
       2015-08-26 00:41:26 +08:00
    不知我理解对不对? @ljbha007
    on_mouse_clicked 是回调函数
    register_mouse_listener (on_mouse_clicked );//登记回调函数
    click_mouse (100, 200 );//触发了回调关联的事件
    if (NULL != mouse_listener )
    (*mouse_listener )(x, y );//调用回调函数 on_mouse_clicked (100,200 );
    miniwoodman
        6
    miniwoodman  
       2015-08-26 01:22:21 +08:00
    理解“回调函数”的前提是了解“函数指针”,之后就自然理解了。

    函数指针是一种指针变量,指向的不是数据,而是函数;函数指针可以作为其他函数的参数。让其他函数可以在内部执行调用,但只能按约定好的格式调用(参数类型和参数个数提前约定好)。

    #include <stdio.h>

    typedef void (*callback_test )(int );

    void func_a (int i ){
    printf ("this func_a () %i \n", i );
    }

    void func_b (int i ){
    printf ("this func_b () %i \n", i );
    }

    void func_c (callback_test func ){
    func (1 );
    func (2 );
    }


    int main (){

    func_c (func_a );
    func_c (func_b );
    }

    ----------------------------------------------------
    输出:
    this func_a () 1
    this func_a () 2

    this func_b () 1
    this func_b () 2
    SoloCompany
        7
    SoloCompany  
       2015-08-26 02:28:19 +08:00
    dont call me
    I will call you
    ljbha007
        9
    ljbha007  
       2015-08-26 08:25:17 +08:00
    kneep
        10
    kneep  
       2015-08-26 09:23:59 +08:00 via iPhone
    回调函数不是语言特性,而是设计思想。
    lancelot
        11
    lancelot  
       2015-08-26 10:07:02 +08:00
    回调是构成面向对象 C 的必要手段。比如说

    typedef UINT32 (* FP_ModInit )(UINT8 ucModID );

    UINT32 ModA_ModInit (UINT8 ucModID );
    UINT32 ModB_ModInit (UINT8 ucModID );
    ......

    然后这样使用(把 ptModStruct 结构的初始化脑补一下)
    case A:
    {
    ptModStruct.Mod_Init = ModA_ModInit;
    ......
    break;

    case B:
    {

    ptModStruct.Mod_Init = ModB_ModInit;
    ......
    break;

    其中左边都是函数指针,右边都是函数名,其实也是函数指针。在不同的 Case 中,我就可以使用相同的函数指针对应到不同的 Mod 初始化函数了。这里是回调的初始化。

    在调用的时候,我统一使用 ptModStruct.Mod_Init (ucModID )就可以了,不用管里面被调用的是什么回调函数。

    以下是度娘百科

    ...因为可以把调用者与被调用者分开,所以调用者不关心谁是被调用者。它只需知道存在一个具有特定原型和限制条件的被调用函数。简而言之,回调函数就是允许用户把需要调用的方法的指针作为参数传递给一个函数,以便该函数在处理相似事件的时候可以灵活的使用不同的方法。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3348 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 12:31 · PVG 20:31 · LAX 04:31 · JFK 07:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.