zoukankan      html  css  js  c++  java
  • 函数指针读书笔记

    • 函数指针的定义格式
    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
    "); }
    void pf_b(void) {    printf("CALL pf_b
    "); }
    void pf_w(void) {    printf("CALL pf_w
    "); }
    
    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.
    ");
    }
    
    void fun_b(int a)
    {
        printf("This is function B.
    ");
    }
    
    void (*pf(void (*fun)(int,int)))(int)
    {
            void (*p)(int);
            
            printf("This is function pf.
    ");
            fun(1,1);
            
            p = fun_b;
            
            return p;
    }
    
    int main()
    {
        pf(fun_a)(1);
        return 0;
    }

    输出结果是:

     参考资料:

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

  • 相关阅读:
    ubuntu下安装maven
    159.Longest Substring with At Most Two Distinct Characters
    156.Binary Tree Upside Down
    155.Min Stack
    154.Find Minimum in Rotated Sorted Array II
    153.Find Minimum in Rotated Sorted Array
    152.Maximum Product Subarray
    151.Reverse Words in a String
    150.Evaluate Reverse Polish Notation
    149.Max Points on a Line
  • 原文地址:https://www.cnblogs.com/Jason-Damon/p/3373101.html
Copyright © 2011-2022 走看看