函数指针

来源:互联网 发布:淘宝怎么查看无线模板 编辑:程序博客网 时间:2024/06/05 17:32
函数指针 是一个指向函数的指针,可以如下定义: 

int (*pfunc)(int, int); 

对这条语句的解释是: 

先解释(*pfunc),所以pfunc首先是一个指针; 

再解释(int, int),pfunc指向一个函数,该函数的参数有两个,都是整形; 

最后是返回值。 

因此,如果定义了一个函数int max(int a, int b),我们就可以这样使用函数指针了: 

pfunc = max; // 注意二者的返回类型,需要一致 




函数指针与指针函数是不一样的,后者是一个函数,其返回值是一个指针,比如 char * index( const char *s, int c); 

int (*max)(int a, int b); // 函数指针 

int *max(int a, int b); // 指针函数 

下面给出函数指针使用的一些代码: 

(1) 

int min(int a, int b)
{
return a > b ? b : a;
}
int max(int a, int b)
{
return a > b ? a : b;
}

int main()
{
int a = 12;
int b = 34;
int (*pfunc)(int, int);// 定义一个函数指针
pfunc = min;
printf("min=%d/n", pfunc(a, b));
pfunc = max;
printf("max=%d/n", pfunc(a, b));
int (*p[2])(int, int);
p[0] = min;
p[1] = max;
printf("min=%d/n", p[0](a, b));
printf("max=%d/n", p[1](a, b));
#define abc min
printf("min=%d/n", abc(a, b));
#define efg max
printf("max=%d/n", efg(a, b));
return 0;
}

int (*p[2])(int, int)是一个函数指针数组。函数指针感觉和#define相似,见上面的代码中的#define部分。 

(2) 

typedef struct point
{
double x;
double y;
}Point;

int cmp1(void *a, void *b)
{
int *c = (int *)a;
int *d = (int *)b;
return *c - *d;
}

int cmp2(void *a, void *b)
{
double *c = (double *)a;
double *d = (double *)b;
double e = *c - *d;
if (e > 0)
return 1;
else if (e < 0)
return -1;
else return 0;
}

int cmp3(void *a, void *b)
{
return strcmp((char *)a, (char *)b);
}

int cmp4(void *a, void *b)
{
Point *c = (Point *)a;
Point *d = (Point *)b;
double e = c->x - d->x;
if (e > 0)
return 1;
else if (e < 0)
return -1;
else return 0;
}

void test(void *a, int n, int size, int (*p)(void *, void *))
{
void *p1 = a;
void *p2 = a + size;
// do something
printf("%d/n", p(p1, p2));

}

int main()
{
int c[2];
c[0] = 12;
c[1] = 34;
test(c, 2, sizeof(int), cmp1);
double d[2];
d[0] = 1.2;
d[1] = 3.4;
test(d, 2, sizeof(double), cmp2);
char s[2][16] = {"xiao", "she"};
test(s, 2, sizeof(s[0]), cmp3);
Point pt[2];
pt[0].x = 1.8;
pt[0].y = 1.3;
pt[1].x = 1.4;
pt[1].y = 1.5;
test(pt, 2, sizeof(Point), cmp4);
return 0;
}

例子(2)中的test函数其中一个参数是一个函数指针,分别调用不同的比较函数,以处理不同类型的数据。和qsort是不是很相似?

在很多情况下,尤其是读别人所写代码的时候,对C语言声明的理解能力变得非 常重要,而C语言本身的凝练简约也使得C语言的声明常常会令人感到非常困惑,因此,在这里我用一篇的内容来集中阐述一下这个问题。

  问题:声明与函数 
有一段程序存储在起始地址为0的一段内存上,如果我们想要调用这段程序,请问该如何去做? 
答案
答案是(*(void (*)( ) )0)( )。看起来确实令人头大,那好,让我们知难而上,从两个不同的途径来详细分析这个问题。 
答案分析:从尾到头

首先,最基本的函数声明:void function (paramList);
最基本的函数调用:function(paramList);
鉴于问题中的函数没有参数,函数调用可简化为 function();
其次,根据问题描述,可以知道0是这个函数的入口地址,也就是说,0是一个函数的指针。使用函数指针的函数声明形式是:void (*pFunction)(),相应的调用形式是: (*pFunction)(),则问题中的函数调用可以写作:(*0)( )。
第三,大家知道,函数指针变量不能是一个常数,因此上式中的0必须要被转化为函数指针。

我们先来研究一下,对于使用函数指针的函数:比如void (*pFunction)( ),函数指针变量的原型是什么? 这个问题很简单,pFunction函数指针原型是( void (*)( ) ),即去掉变量名,清晰起见,整个加上()号。
所以将0强制转换为一个返回值为void,参数为空的函数指针如下:( void (*)( ) )。
OK,结合2)和3)的分析,结果出来了,那就是:(*(void (*)( ) )0)( ) 。 
答案分析:从头到尾理解答案 
(void (*)( )) ,是一个返回值为void,参数为空的函数指针原型。
(void (*)( ))0,把0转变成一个返回值为void,参数为空的函数指针,指针指向的地址为0.
*(void (*)( ))0,前面加上*表示整个是一个返回值为void的函数的名字
(*(void (*)( ))0)( ),这当然就是一个函数了。
我们可以使用typedef清晰声明如下:
typedef void (*pFun)( );
这样函数变为 (*(pFun)0 )( );

  问题:三个声明的分析 
  对声明进行分析,最根本的方法还是类比替换法,从那些最基本的声明上进行类比,简化,从而进行理解,下面通过分析三个例子,来具体阐述如何使用这种方 法。
#1:int* (*a[5])(int, char*);
首先看到标识符名a,"[]"优先级大于"*",a与"[5]"先结合。所以a是一个数组,这个数组有5个元素,每一个元素都是一个指针,指针指向" (int, char*)",很明显,指向的是一个函数,这个函数参数是"int, char*",返回值是"int*"。OK,结束了一个。:)

#2:void (*b[10]) (void (*)());
b是一个数组,这个数组有10个元素,每一个元素都是一个指针,指针指向一个函数,函数参数是"void (*)()"【注10】,返回值是"void"。完毕!
注意:这个参数又是一个指针,指向一个函数,函数参数为空,返回值是"void"。

#3. doube(*)() (*pa)[9];
pa是一个指针,指针指向一个数组,这个数组有9个元素,每一个元素都是"doube(*)()"(也即一个函数指针,指向一个函数,这个函数的参数为 空,返回值是"double")。 

int main(){    /* Function prototypes */    long lift( int ), step( int ), drop( int );    void work( int number, long (*function)(int i) );    int select, count;    .    .    .    select = 1;    switch( select )     {        case 1: work( count, lift );                break;        case 2: work( count, step );                break;        case 3: work( count, drop );                /* Fall through to next case */        default:                break;    }}/* Function definition */void work( int number, long (*function)(int i) ){    int i;    long j;    for ( i = j = 0; i < number; i++ )            j += ( *function )( i );}