函数(*foo[])()的使用

函数指针数组的使用场景、局限和优点

原文地址:http://blog.csdn.net/qq_34861102/article/details/78085180


  • 函数名

    每个函数都有一个入口地址,该入口地址就是函数指针所指向的地址,函数名即为入口地址。

    int foo(int x){
        return x;
    }

    foo为函数名


  • 函数指针

    函数指针是指向函数的指针变量,每个函数都有一个入口地址,指针变量中保存函数的入口地址,有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样。

    函数指针的声明方法为:

    void(*fp)();

    返回值类型 (指针变量名) ([形参列表]);*


  • 函数指针数组的使用场景

    函数指针数组即函数指针的数组。

    在使用C语言构造解释器的过程中,对于词法分析得到的Token在进行语法分析的过程中,对于不同的类别的Token此处函数需要进行一个识别。输入参数假定为int* buffervoid* value,其中int* buffer用来识别Token的类型,如浮点数、整数等;void* valueToken的具体值。假设此处没有封装成一个类,仅仅是一个主函数需要对不同接受类型的Token进行不同的函数调用,假设有100种不同的类型。

    若按通常做法,会写出如下代码:

    void MyFuntion( int* buffer, void*value ){
        switch(buffer[0]){
            case 1 :
                function1();
                break;
            case 2 :
                function2();
                break;
            case 3 :
                ...... 
            case 100:
                function100();
                break;
        }
    }  

    按照这种写法,每一次对于不同的Token都要进行多次判断之后才能找到正确的函数处理函数,代码的执行效率较低,这里就可以适用函数指针数组的概念解决多次判断的问题。

    按函数指针数组的思路,会写出如下代码:

    void funtion0(void); 
    ......
    void funtion100(void); 
    void (*fun[100])(void) = {funtion0,......,funtion100};
    
    void MyFuntion( int* buffer, void*length ){
        (*fun[buffer[0]])();
    }  

    只要2行代码,就完成了100条case语句要做的事,减少了编写代码时工作量,从代码执行效率上来说,直接调用函数指针,也比case语句高。

    给一个可运行的实际案例:

    
    #include <stdio.h>
    
    
    #include <stdbool.h>
    
    
    #define swap(x,y) {typeof(x) t = x; x = y; y = t;}
    
    
    bool rule1(int x, int y){
        return x > y;
    }
    
    bool rule2(int x, int y){
        return x < y;
    }
    
    bool rule3(int x, int y){
        return x%3 < y%3;
    }
    
    void sort(int *a,int n, bool (*f)(int,int)){
        for (int i = 0; i < n - 1;i ++){
            for (int j = 0; j < n - 1;j ++){
                if (f(a[j],a[j+1]))
                    swap(a[j],a[j+1]);
            }
        }
    }
    
    void print(int *a,int n){
        for (int i = 0; i < n; i ++){
            printf("%d",a[i]);
        }
        printf("\n");
    }
    
    int main(){
        int a[10] = {2,1,3,8,0,4,6,5,7,9};
        //定义函数指针数组
        bool (*f[])(int,int) = {rule1,rule2,rule3};
        sort(a,10,f[0]);
        print(a,10);
        return 0;
    }

  • 使用场景的分析

    • 局限性

      无法对参数(parameter)和返回值(returnvalue)的类型进行检查,因为函数已经退化成指针,指针是不带有这些类型信息的

      实际测试:

      bool rule1(int x, int y){
          return 'x > y';
      } 

      将返回值修改为非bool类型的字符串,可以看到程序是可以运行的,但是运行结果出现与预期结果不相符合。

      可以看到这里的返回值(returnvalue)是没有检查的

    • 优点

      优点从上面的应用实例中可以明显看出,减少代码的编写工作量、提高代码的运行效率,尤其是对未定函数的存在的场景适用。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值