• 函数指针与回调函数新感悟


    2021年5月22日12:57:47

    关于函数指针的理解可以参考之前写的博文。

    对于一个指针而言,我们需要考察它的几点性质:

    • 1、这个指针是什么类型的?
    • 2、这个指针的大小是多少?
    • 3、这个指针是什么时候指向什么地址的?

    其实,我们对于一个指针一般只关注两点,1和3.

    对于1,肯定是在声明的时候就知道这个指针应该指向什么类型。
    对于2,肯定是在赋值的时候知道它指向对应的类型的地址的。
    对于3,指针的大小和系统有关,一般的系统,指针大小为4字节,也就是和int类型的大小一样。

    明确以上1,2点之后,我们对照着int *来看就会很明白了。

    int a = 0;
    int * p;
    p = &a;
    

    那么接下来我们聊聊函数指针。
    现在再回顾一下,我用自己的语言来描述一下什么是函数指针。
    函数指针 本质是一个指针。
    结合上面关于指针的2点需要关注的点,我们对照一下函数指针该怎么去解释或者说理解。

    像声明int类型的指针一样,我们应该声明一个函数类型的指针。
    这个时候的疑问是,系统里没有我们需要的函数类型啊。
    那怎么办?
    别忘了一件事:
    C语言为我们提供了声明自定义类型的工具:那就是typedef关键字。
    我们一般使用这个关键字做结构体的声明,在声明结构体的时候还要结合另外一个关键字struct。

    typedef struct person_s { //这里后缀s是认为添加的,我们可以理解成使用person_s这个结构体时候,必须和struct一起使用,因为现在的结构体名字是struct person_s 而不是person_s
        int age;
        char sex;
        double height;
        double weight;
    };
    

    从上面可以看到typedef的一种用法就是用来声明结构体。
    还有另外一种就是为类型取别名。

    typedef struct person_s person_t;
    

    通过上面这个语句,我们就成功的为struct person_s 取了一个别名,也就是一个外号:叫person_t。 这个时候我们在需要使用struct person_s 的地方可以使用person_t进行替换了,是不是方便很多?

    ok。
    到这里我们认识了typedef的取别名的用法。
    回到正题。声明函数类型的指针,肯定需要一个函数类型了。
    那么我们就用typedef来声明一个函数为了就行了。

    typedef void * (*FP)(int *, int);
    

    上面这句话就是为函数void * (*)(int *, int);取了一个别名叫FP。

    那么我们就可以使用fp去声明一个指针了。

      FP *fp1;  //这样fp1就必须指向一个形如void * (*)(int *, int)的函数。
      int a[] = {1,2,3,4,5,6,7,8};
      int n = 3;
      void * sumArray(a, n);//此函数在其他地方声明和实现的,计算一个数组前n的和并返回该值的地址(这个例子不好,主要是返回内容是一个地址了)
      //上面这个函数就是FP类型的。我们可以使用fp1来替换sumArray函数进行调用
      fp1 = sumArray;
      fp1(a,n);//这样就可以和直接调用sumArray一样的效果。
    

    好,从上面的例子,我们隐约能够觉得,函数指针是可以被赋值的,也是可以当做被赋值过来的函数进行调用的。
    慢慢品味这里的逻辑。
    有了这个意识之后,我们可以更大胆一点。
    如果在一个结构体里声明了一个函数指针,那么会发生什么?
    看例子:

    typedef void (*EAT)(char *, int);//吃的方法,传入水果的名字和数量,表示吃了几个XX水果
    void (*_eat)(char * name, int n){
        //吃了n个name水果
    }
    typedef struct person_s{
        int age;
        EAT *eat;//
    }person_t;
    
    person_t *xiaoming = (person_t)malloc(sizeof(person_t));//给xiaoming申请一块内存
    //开始给xiaoming赋值
    xiaoming->age =18;
    xiaoming->eat = _eat;//注意这里为xiaoming的eat方法实际赋值了,赋值为_eat方法,看清这里,是直接把函数名赋值给对应的指针
    
    //程序某处需要调用xiaoming的eat方法
    char *name = "Orange";
    int n = 2;
    xiaoming->eat(name,n); //开始执行_eat函数。
    
    

    这个函数的赋值,和在响应需要的时候调用指定函数显示不同的功能的过程,就叫做函数的回调。这个函数就是回调函数。

  • 相关阅读:
    Linux 管道 管线
    中国网络拓扑图(主干网、地区网、主节点一览表)
    C++中的STL中map用法详解
    Git 丢弃本地修改
    Linux下指定so动态库的加载路径的5种方法!!!
    C++中string append函数的使用与字符串拼接
    C++执行shell命令linux
    Linux动态库.so文件加载搜索路径详解
    FFmpeg打印日志函数分析
    linux C/C++中调用shell命令和运行shell脚本
  • 原文地址:https://www.cnblogs.com/dhu121/p/14798663.html
Copyright © 2020-2023  润新知