深入分析C语言函数指针和回调函数(1)

今天,我们必须了解一个称为回调函数的概念。

什么是回调函数?百度的权威解释如下:回调函数是通过函数指针调用的函数。

如果将函数指针(地址)作为参数传递给另一个函数,则当此指针用于调用它所指向的函数时,我们说这是一个回调函数。

回调函数不是由函数的实现者直接调用的,而是在发生特定事件或条件时由另一方调用的,并用于响应事件或条件。

然后,我们来看一个示例:#include& lt; stdio.h& gt;无效print(); int main(void){void(* fuc)();  fuc =打印;  fuc(); }& nbsp; void print(){printf(“您好,世界! ");}从此示例中可以看到,我们首先定义一个函数指针fuc,该函数指针的返回值为void,然后为该函数指针分配一个值,该值是打印的第一个地址功能。

当fuc获得打印的地址时,fuc的地址等于打印的地址,因此对fuc()的最终调用是:等效于调用print();那么我写的例子显然与百度的解释不一致吗?定义是:如果将函数指针(地址)作为参数传递给另一个函数,则当此指针用于调用所指向的函数时,我们说这是一个回调函数。

的确是不同的,但事实是一样的,接下来让我们看一个例子。

#include& lt; stdio.h& gt; int add_ret(); int add(int a,int b,int(* add_value)()){返回(* add_value)(a,b);} int main(void){int sum = add(3,4,add_ret); printf(“ sum:%d " sum);返回0; }& nbsp; int add_ret(int a,int b){return a + b;}从此示例中,我们看到:这不符合我们的定义吗?让我们把函数的指针(地址),这里是add_ret,作为参数int add(int a,int b,int(* add_value)()),这里的参数是int(* add_value)(),名称可以无论您想要什么,都可以使用它,但是它必须符合C语言的命名约定。

当使用此指针来调用它所指向的函数时,我们说它是一个回调函数。

我们在add函数中看到return(* add_value)(a,b);这(* add_value)(a,b)等效于对指针的简单引用。

在main函数中,我们传入要实现的特定函数add_ret,此函数非常简单,就是将两个数字相加并返回,就在这里好,简单的引号等效于取出返回值中的值指针,此值返回a + b,这是我们在a和b中传递的两个数字相加的结果。

& nbsp;& nbsp;& nbsp;& nbsp;& nbsp; & nbsp;& nbsp;那么,回调函数到底是做什么的呢?在这一点上,用户和开发人员之间存在一个概念。

例如,刚才提到的add()函数。

假设用户实现了add_value函数,而开发人员实现了add_value函数,则用户没有做太多的工作,只想通过开发人员实现这样的接口,然后调用开发人员实现的接口的返回值即可。

函数,然后实现我们此开发人员的功能。

该开发人员有许多角色,这些角色可以是他公司的核心开发人员,也可以是其他工作的外包商。

此时,他作为开发人员的角色就可以完全实现add_value。

add_ret函数被封装并加密,然后向用户抛出.so或.a,这样用户就看不到add_ret的具体实现内容,用户只需要开发人员向他提供.h和.so,以此方式,作为开发人员,他将自己实现的功能保密。

      & nbsp;& nbsp;& nbsp;& nbsp;& nbsp;& nbsp;& nbsp;我们在目录中创建三个文件main.c,vendor.c,vendor.h& nbsp;& nbsp;& nbs p;& nbsp;& nbsp;& nbsp;& amp; ; nbsp; Main.c由用户开发。

Vendor.c和vendor.h由开发人员实现。

在main.c中,代码如下: #include“ vendor.h” int add(int a,int b,int(* add_value)()){返回(* add_value)(a,b);} int main(void){int sum = add(3,4,add_ret); printf(“ sum:%d " sum);返回0; }& nbsp; vendor.c,代码如下:#include“ vendor.h” int add_ret(int a,int b){返回a + b;} vendor.h,代码如下:#ifndef __VENDOR_H #define __VENDOR_H int add_ret(int a,int b); #endif接下来,我们创建一个动态链接库,最后,开发人员密封了vendor.c的内容,并向用户提供了vendor.h。

在linux下创建一个动态链接库,并将vendor.c和vendor.h打包到一个动态链接库中