• callback用法简介


    源地址:https://argcv.com/articles/2669.c

    callback,函数的回调,从ANSI C开始,一直被广为使用。无论是windows API的所谓消息机制,动态链接库的调用,还是sqlite的命令,gcc下的pthread,qsort。callback都在其中起着难以替代的作用。

    那么,callback为何如此受到亲睐呢?因为它可以以一个函数为参数,放到参数列表交给API,让API调用。比如有个文件夹下有一千万个文件,我们希望对每个文件进行一些处理,比如查看文件长度是否超过512字节。而遍历这个文件夹的程序是个API。如果不使用callback,API可能有两种办法,一种是申请一个超巨大的空间,然后把找到的所有文件名都放进去,然后返回这个空间(类似的还有把这组文件名写到文件中,一个意思),这样速度的确很快,而且简单方便,但问题是,一千万个文件,占用的空间是如此的庞大,空间复杂度为O(n),而我们只是要对每个文件进行一点小小的处理而已,实在是杀鸡焉用宰牛刀。另一个方法是搞个迭代器,每次只返回一个文件名,下次调用再返回下个。为了线程安全,每次传参都得来个指针之类的记录自己的进度。如果做的细心,也可以做的很快,也不占用空间。但问题是,只是个简单的遍历文件夹的API,这么折腾好累哦。而如果使用callback,事情就简单很多了。主程序调用API,把处理文件的函数用参数的方法传递给API,API每找到一个文件名,就调用这个函数,当场处理不用存储任何文件名。这样空间复杂度是O(1),而且方便有效,何乐而不为呢?

    callback具体怎么实现的呢?我在本文中做一个小小的demo。
    Demo的实现的功能是这样的:
    bar.c调用foo.c的一个函数,请求给一个magic number。但foo.c的函数并不是直接返回,而是调用bar.c传递过来的函数use_magic_num,把magic number 作为参数使用进去。

    首先,定义最后要被调用的函数use_magic_num如下:

    1
    2
    3
    4
    5
    6
    void use_magic_num(int magic_num);
     
    void use_magic_num(int magic_num)
    {
        printf("bar.c : magic number is %d ", magic_num);
    }

    也就是传进去一个参数,然后函数会打印出这个magic number。它被放置在bar.c下

    然后foo.h中定义API get_magic_num的原型

    1
    void get_magic_num(void (*callback)(int magic));

    它的参数列表和普通的有点区别,传入的是一个函数指针,这个函数必须是原型为有一个int类型为参数,返回为void。其他的就和普通的函数一样了。

    对get_magic_num进行实现。

    1
    2
    3
    4
    5
    6
    7
    typedef void (*foo_run_magic)(int);
     
    void get_magic_num(foo_run_magic foo)
    {
        int magic = 9;
        foo(magic);
    }

    我么可以看到,在这儿,我做了点小花招,我typedef了这个函数指针,这样我们可以直接使用foo_run_magic来代替麻烦的各种括号的函数指针了。
    然后调用 foo,其实就是调用传入的参数。在本工程中,也就是前面写的use_magic_num了。
    虽然foo.c完全看不见use_magic_num,但完全不妨碍函数的使用。

    最后定义bar.c的主程序

    1
    2
    3
    4
    5
    int main(int argc,char *argv[])
    {
        get_magic_num(use_magic_num);
        return 0;
    }

    也就是调用foo并传入use_magic_num的函数了。

    编译和执行结果大致是如下的样子:

    1
    2
    3
    4
    5
    6
    7
    [yu@argcv callback]$ make
    gcc -c -Wall -std=c99 bar.c -o bar.o
    gcc -c -Wall -std=c99 foo.c -o foo.o
    gcc -Wall -std=c99 -o bar bar.o foo.o
    [yu@argcv callback]$ ./bar
    bar.c : magic number is 9
    [yu@argcv callback]$

    完整的工程请参考此处

  • 相关阅读:
    398. Random Pick Index
    382. Linked List Random Node
    645. Set Mismatch
    174. Dungeon Game
    264. Ugly Number II
    115. Distinct Subsequences
    372. Super Pow
    LeetCode 242 有效的字母异位词
    LeetCode 78 子集
    LeetCode 404 左叶子之和
  • 原文地址:https://www.cnblogs.com/lanye/p/5363515.html
Copyright © 2020-2023  润新知