一. 函数指针
说到指针,我们可以想到的是取地址操作符
int ADD(int a,int b)
{
return a+b;
}
int main()
{
printf("%p\n", &ADD);
return 0;
}
如此,我们便可以得到一个地址
而我们便可以将这个地址存入到一个函数指针中
int(*p)(int,int)=&ADD
类似于数组指针,我们可以采用类似的方法来思考,其中*表示p为指针变量,int表示函数的返回值的类型,而(int ,int)表示的是函数参数的类型
然而事实上,函数名本身所代表的就是函数的地址,与&函数名一致
int ADD(int a,int b)
{
return a+b;
}
int main()
{
printf("%p\n", &ADD);
printf("%p\n", ADD);
return 0;
}
我们可以看到,test与&test所代表的地址都是相同的
因此,我们也可以将函数指针写作这样
int(*p)(int,int)=print
而在使用时,与指针类似,我们可以解引用后使用
printf("%d",(*p)(2,3));
而事实上,不进行解引用操作直接使用也是可以的
printf("%d",p(2,3));
我们来看两端有趣的代码
//代码1
(*(void (*)())0)();
//代码2
void (*signal(int , void(*)(int)))(int);
首先代码1,我们可以由内到外来分析,首先,void(*)()是一个函数指针类型,无返回值,无参数。而(void(*)())0也就表示将地址为0的函数指针进行强制类型转换。而转换后外层的(* )()表示该函数指针解引用后进行使用。
而代码2,首先我们可以确定signal为一个函数名,它有两个参数int 和void(*)(int),在分离 signal(int , void(*)(int))后,剩下void(* )(int),可以得知是一个函数指针的类型,因此signal的返回类型也应该是一个函数指针
而将代码2简化后,也会更容易理解
typedef void(*pfun_t)(int);
pfun_t signal(int, pfun_t);
二. 函数指针数组
在上面,我们学习了函数指针,而函数指针数组也就很好理解了,就是一个存放函数指针的数组
例如若是想要实现一个简易的计算器(加减乘除)
需要分别自定义四个函数来实现这些功能
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
int mul(int a, int b)
{
return a * b;
}
int div(int a, int b)
{
return a / b;
}
由于参数类型、参数个数、返回类型都相同,我们可以将这四个函数放在一个函数指针数组中,以便于调用
int(*p[4])(int a, int b) = { add, sub, mul, div };
同样,int 表示函数返回值类型,*表示指针,[4]表示这是一个数组,(int a, int b)表示函数参数
这样也就方便函数的调用
三. 指向函数指针数组的指针
没啥好解释的,就想名字一样
int(*p[4])(int a, int b) = { add, sub, mul, div };
int(*(*pp[4]))(int a, int b)=&p;
四. 回调函数
概念
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个
函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数
的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进
行响应。
紧承上面所讲的计算器,但我们不再使用函数指针数组
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
int mul(int a, int b)
{
return a * b;
}
int div(int a, int b)
{
return a / b;
}
首先,回调函数的参数应该是函数指针
int calc(int (*pf)(int int))
{
}
而当我们想要实现计算器,只需要将对应函数的地址(函数名)传给回调函数即可
calc(add);
而calc内部,也是比较容易实现的
int calc(int (*pf)(int int))
{
int a=0;
int b=0;
int ret=0;
scanf("%d,%d",&a,&b);
ret=pf(a,b);
return ret;
}
qsort函数
同样,qsort函数中也是一个典型的回调函数
在分析回调函数之前,我们先来了解一下qsort函数
我们可以看到,这个函数有四个参数,分别是base:数组首元素地址、num:数组大小、size数组类型大小以及compar这个用作比较两个元素的函数
而我们主要是来考虑这个compar函数
大致分析一下,就是比较两个元素,并分情况-1,0,1
而参数的类型为const void*,无法直接使用,需要进行强制类型转换才可以。
而既然小于返回负数,等于返回0,大于返回正数,我们就可以直接返回两数相减的值即可
int compar(const void * p1, const void * p2)
{
return (*( int *)p1 - *(int *) p2);
}