Visitors hit counter dreamweaver

函数指针读书笔记

  • 函数指针的定义格式
  1. <返回类型> (*<指针变量>)(<形参表>)   例如:

 

int  f(int);
int (*pf)(int) = &f;

 

  pf是一个函数指针,它能够指向的是参数为int类型并且返回值为int类型的函数

  2.  也可以用typedef为函数指针类型取一个名字,然后再用该函数指针类型来定义指针变量:

      typedef  <返回类型>  (*<函数指针类型名>)(<形参表>)。

 

typedef double (*PF)(double);
PF pf;

 

  第一行是对一个函数指针进行了定义声明,声明了一个具有double返回值,并且参数是double类型的函数指针。以后就可以用PF来声明其它的相同类型的函数指针。

  • 函数指针的用途
    • 转换表(jump table)
    • 作为参数传递给另一个函数

 

       作为参数传递给另一个函数   用法主要是回调函数(callback function),也就是用户把一个函数指针作为参数传递给其它函数,后者将“回调”用户的函数。一个很常用的例子就是c函数库的qsort函数, qsort并不知道进行比较的值的类型,这是我们就可以传入一个比较函数的函数指针,对于不同类型的比较,我们可以让这个函数指针绑定到不同的函数上。这里就不详细说了。

    转换表  对于用户的不同输入,我们要调用不同的函数实现不同的功能,这时候也许我们可以用switch语句来实现。但是当每次我要增加一些操作的时候,就必须修改switch,也就是修改main函数里面的代码,这样是非常不方便的。那我们就可以用跳转表来实现,跳转表其实就是一函数指针数组。一般的用法如下[1]:

  

  代码实现如下:

#include <stdio.h>

typedef void (*PF)(void);

struct jump_table{
    char ch;
    PF pf;
};

void pf_a(void) {    printf("CALL pf_a\n"); }
void pf_b(void) {    printf("CALL pf_b\n"); }
void pf_w(void) {    printf("CALL pf_w\n"); }

struct jump_table table[100] = {  //跳转表
    {'a',pf_a},
    {'b',pf_b},
    {'w',pf_w},
    {0,NULL}
};

int main()
{
    char ch;
    int i;

    while( (ch = getchar()) != 'x')
    {
        i = 0;
        while ((table[i].ch != 0))
        {
            if (ch == table[i].ch)
            {    
                table[i].pf();
                break;
            }
            i++;
        }
    }
}

2013/10/16  22:33

  我们可以看到用户输入的key值是不连续的,所以我们必须每次都扫描一遍数组,同时我们在定义数组的时候要设置结束标志,这样能方便判断结束。

  但是如果用户输入的是从零开始的连续整数,或者是一些诸如连续字符a-z之类的,那么我们就可以直接跳转到相应的项,而不需扫描数组。比如我们在做计算器的时候,我们把ADD定义为0,SUB定义为1....[2],那么就可以如下的定义:

double add(double, double);
double sub(double, double);
double mul(double, double);
double div(double, double);
....

double (*oper_func[])(double,double) = {
    add,sub,mul,div,.....
};

  

然后通过下面来调用相应的操作函数,oper为输入的值:

result = oper_func[oper](op1, op2);

oper_func从数组中选择正确的函数指针,而函数调用操作符将执行这个函数。当然,我们这里还需要的注意的是数组越界问题,为了保证所使用的下标位于合法的范围内,在一开始的时候我们可以先检查下标的合法性,然后再进行调用操作。

  •  参考资料
    •   [1] 我们老师上课的课件,具体解释权归老师所以;
    •       [2] 《C和指针》

 

复杂函数指针的应用

  来看下下面这个代码:

void (* pf(void (*fun)()))()

  咋第一眼看上去有点头晕呢!那么多括号,那么多嵌套。莫急莫急!我们来把它细分一下,首先看 void (*fun)(),这就是我们前面看到的函数指针,这个没问题。然后再看看

pf(void (*fun)()),pf不也是一个函数嘛,只不过它的参数是一个函数指针罢了。那么如果我们令pf(void (*fun)())为X,那么那一整个式子可以表示成:void(*X)(),这就是函数指针的定义。说明X又是一个函数指针,也就是说函数pf的返回值又是一个函数指针。这样就都清楚啦,再来屡一下:pf这样一个函数:接受参数为函数指针,而且pf的返回值也是个参数为void返回值为void的函数指针。

而且我们还可以用下面这两个定义来表示上面这个函数定义,这样看起来就明了多了:

 

typedef  void  (*PF)();
PF pf(PF fun);
typedef void PF();
PF *pf(PF *fun);

 从下面这个定义方式,我们就可以很明确的看到pf函数的参数是一个PF*类型,返回值也是一个PF*类型的函数。


 

下面用一个程序来看看这个应用的例子:

 

#include <stdio.h>

void fun_a(int a,int b)
{
    printf("This is function A.\n");
}

void fun_b(int a)
{
    printf("This is function B.\n");
}

void (*pf(void (*fun)(int,int)))(int)
{
        void (*p)(int);
        
        printf("This is function pf.\n");
        fun(1,1);
        
        p = fun_b;
        
        return p;
}

int main()
{
    pf(fun_a)(1);
    return 0;
}

输出结果是:

 

 参考资料:

http://bbs.csdn.net/topics/30344321

 

posted @ 2013-10-16 22:52  Jason Damon  阅读(409)  评论(0编辑  收藏  举报