声明:
本文是阅读周立功老师的程序设计与数据结构后所写,很多内容其实是书中的内容,所以如果您想了解更多这方面的知识,您可以阅读这本书。
在前面一节我们简单介绍了指针、数组、指针数组以及数组指针。而在这一节中我们主要介绍两个概念:函数指针函数以及函数指针。
指针函数:
说到指针函数,他的主体还是一个函数,但是他的返回值为指针类型,因此我们通常将其称为指针函数。他通常的形式为:
int* iMax(int *a, int *b);
注意在上面的函数中对于形参我们同样使用指针的方式,这是因为只有将实参(调用函数中的变量)以地址的方式传递给调用函数的形参才可以对其进行修改或者对其地址进行操作,而如果以实参值的方式传递给形参将只是值得复制,而并不会对实参的值有所操作。而在指针函数中我们很多时候是使用传址的方式来传递实参。这是因为只有这样在返回时才可以获得主调函数中实参的操作地址。而对于传值的情况,在被调函数操作完后函数的栈空间将被清零,所以此时传递出的地址也并不一定是我们想要的地址。
其实指针函数在我们平时的程序写作中还是比较常见的,当我们需要对形参进行操作并将操作后的形参地址返回给主调函数时通常会用到指针函数。
函数指针:
对于函数指针我想大家可能就不那么熟悉了,但是如果你要写嵌入式驱动程序那么你将经常用到这样的函数指针,函数指针的形式如下:
int (*compare)(void *a,void *b);
既然我们称他为函数指针,那么他更像是一个函数的指针类型,所以他是一个指向其他函数的指针,而对于指向函数的指针我们通常使用下面的方式来将一个函数传递给这个函数指针:
int compare_int(int *a, int *b)
{
return *a - *b;
}
int compare_conv(int *a, int *b)
{
return *b - *a;
}
compare = compare_int;
compare(&a, &b);
compare = compare_conv;
compare(&a, &b);
我们知道在内存中一个函数的函数名所在位置为函数的首地址,所以我们使用函数指针指向这个地址之后就可以调用这个函数的代码,即对这个函数进行操作了。
回调函数:
而对于函数指针来说最常用的一种方式就是回调函数了,回调函数的形式为:
上图中紫框表示上层主调函数,而蓝框表示下层被调函数,其中黑色箭头表示调用关系,而棕色箭头表示返回关系。而在上面的函数3通常表示回调函数。
下面我们以一个例子向大家说明:
int compare_int(int *a, int *b)
{
return *a - *b;
}
int compare_conv(int *a, int *b)
{
return *b - *a;
}
typedef int (*Compare)(void *a, void *b);
int compare_num(int *a, int *b, Compare compare)
{
return compare(a, b);
}
int main(int argc,int **argv)
{
int a = 4, b = 5;
int tmp;
tmp = compare_num(&a, &b, compare_int);
printf("The different is %d \n",tmp);
tmp = compare_num(&a, &b, compare_conv);
printf("The different is %d \n",tmp);
return 0;
}
上面的函数就是一个通过正序和倒序比较两个数字差的例子,从上面可以看出我们即可以正着比较同样也可以反着比较。而我们使用main函数作为上层函数调用下层函数compare_num函数,同时我们又会将两种不同的比较方式传递给下层函数compare_num。通过上面这种回调我们可以动态的改变代码和方式来来实现我们编程的目的。