C语言中的函数指针与回调函数
1.函数指针的使用
- 通常我们使用的指针都是变量指针,它们可以指向整形变量、字符型变量、浮点型变量等,指针内存放的是变量的地址,我们可以通过指针来操作变量。
例如:
#include <stdio.h>
int main()
{
int a = 10;
int *p = &a;
*p=20;
printf("a=%d\n",a);
return 0;
}
-
而函数指针,顾名思义,就是指向函数的指针,C程序在编译时每一个函数都有一个入口地址,函数指针内存放的其实就是这样的入口地址。函数指针有两个用途:调用函数和做函数的参数。其中函数指针用作函数的参数可以实现回调函数。
-
函数指针的变量声明如下,它主要包括三个部分 *返回值类型 (函数指针名)(参数列表)
int (*fun_ptr)(int,int); // 声明一个指向同样参数、返回值的函数指针fun_ptr
- 例如使用函数指针来调用函数:
#include <stdio.h>
void haha()
{
printf("haha\n");
}
int main()
{
void (*p)() = &haha; //也可以去掉&,因为函数名被编译后就是一个地址
haha();
(*p)();//按照我们之前对指针的理解,我们会这样使用函数指针
p();//实际上我们还可以这样使用,这应该是编译器帮我们做了优化
return 0;
}
- 为了使用的方便,函数指针常与typedef一起使用
#include <stdio.h>
typedef void (*PTRFUN)(int,int);//声明了一种函数指针类型PTRFUN,它可以指向返回值为void,参数列表为(int,int)类型的函数,可以类比结构体的typedef
void haha(int a, int b)
{
printf("haha: a=%d,b=%d\n", a, b);
}
void xixi(int a, int b)
{
printf("xixi: a=%d,b=%d\n", a, b);
}
int main()
{
PTRFUN ptr1 = haha;//创建了PTRFUN这种类型的函数指针ptr1
PTRFUN ptr2 = xixi;//创建了PTRFUN这种类型的函数指针ptr2
ptr1(1,2);
ptr2(3,4);
}
2.什么是回调函数?为什么要使用回调函数?
- 回调函数是一个参数,它被传递给其他函数
- 回调函数可以看作是我们封装起来的一系列操作,有了它的存在,我们就可以通过函数传参的方式替换函数中的某些不确定的操作,将这部分内容交给用户去实现,提高了代码的可复用性。
- 回调函数作为一个需要被传递给某个函数的参数,它有几部分是固定了的(返回值,参数列表),剩余部分需要我们自己写(函数名,花括号内的函数体),这和函数指针有关,当我们要把回调函数作为参数传递给某个函数时,我们对这个函数的定义是确定的,这个函数的参数列表中一定有一个函数指针用于接收我们的回调函数,根据上面所讲的函数指针的特点就可以明白。
- 下面是一个使用回调函数的例子,简单模拟判断服务器是否建立连接
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void call_back(int success)
{
if(success)
printf("Connect successfully!\n");
else
printf("Connect failed!\n");
}
int connect(void (*fuc_ptr)(int))
{
srand(time(0));//以时间作为随机数种子
int state = rand()%2;//获得随机状态,只有两种状态0和1
fuc_ptr(state);
return state;
}
int main()
{
void (*p)(int) = call_back;
printf("state= %d", connect(p));
return 0;
}