• 再论函数指针、函数指针数组



    一、基本概念
    数组名:本质是指向数组第一个元素的常量指针,即数组首地址
    函数名:本质是指向函数第一条指令的常量指针,即函数首地址
    函数指针:保存了函数首地址,可以看做函数的别名


    二、函数指针的声明方法
    type (*func)(type &, type &)
    1、该语句声明了一个指针func,它指向了一个函数;
    2、该函数带有2个type型参数,并返回一个type型的值;
    p.s. tpye类型可以看做int或者float等C++类型
    3、可以把整个函数看做一个数据类型
    tpye func(type, type)
    指针变量func就指向这样的数据类型


    三、注意事项
    1、一个指向函数的指针必须保证该函数被定义了,且被分配了内存,
    否则它指向一个空地址,这可是大忌!
    2、特别注意第一个括号的位置,如果把括号去掉
    type *func(type &, type &)
    就变成了一个返回type *类型的函数了


    四、函数指针应用举例
    1、通过函数指针调用函数
    # include <stdio.h>
    void f(int x)
    {
    printf("%d ", x);
    }
    int main()
    {
    f(10); //直接调用函数f
    void (*p)(int); //定义一个函数指针p
    p = f; //对指针变量p赋值,函数名f即为函数首地址 ,p=&f也正确
    (*p)(20); //通过指针而非函数名调用函数
    return 0;
    }
    2、函数指针的typedef用法
    typedef void (*PINT)(int) ; //声明该函数结构void f(int)为一个数据类型
    PINT是该数据类型的名字
    //注意区别于结构体的typedef用法
    PINT p;
    p = f;
    3、函数指针作为函数参数
    设计一个CallMyFun函数,这个函数可以通过参数中的函数指针值不同来分别调用
    MyFun1、MyFun2、MyFun3这三个函数(注:这三个函数的定义格式应相同)。
    # include <stdio.h>
    typedef void (*PM)(int); //定义新的函数数据类型为PM
    void CallMyfun(PM p, int x) //函数指针作为形参
    {
    p(x);
    }
    void MyFun1(int x)
    {
    printf("MyFun1 = %d ", x);
    }
    void MyFun2(int x)
    {
    printf("MyFun2 = %d ", x);
    }
    void MyFun3(int x)
    {
    printf("MyFun3 = %d ", x);
    }
    int main()
    {
    CallMyfun(MyFun1, 10);
    CallMyfun(MyFun2, 20);
    CallMyfun(MyFun3, 30);
    return 0;
    }


    五、再次深入学习
    1、*(int*)&p ----这是什么?
    void Function()
    {
      printf("Call Function! ");
    }<br>
    int main()
    {
      void (*p)(); //定义函数指针变量p
      *(int*)&p=(int)Function;//&p求指针变量p的地址,这是一个32位的二进制数
    //(int *)&p表示将地址强制转化为指向int型数据的指针
    //(int)Function表示将函数入口地址强制转换成int型数据
      (*p)();
      return 0;
    } 
    2、(*(void (*)(void))(0x30700000)()--这是什么?
    void (*reset)(void) = (void (*)(void))0
    reset();
    等式左边为定义函数指针reset;
    等式右边为强制类型转换,将数值“0”强行转换为函数指针地址“0”;
    下一句表示调用函数reset(),从地址"0"处开始执行;
    举例:
    void (*theUboot)(void); //定义函数指针theUboot
    theUboot = (void (*)(void))(0x30700000);//将绝对地址0x30700000
    强制转换为函数指针地址,然后赋给theUboot
    theUboot(); //调用函数theBoot()

    p.s.以上代码可以合并为下面一行代码:
    (*(void (*)(void))(0x30700000)();
    3、总结
    其实函数指针与普通指针没什么差别,只是指向的内容不同而已。
    使用函数指针的好处在于,可以将实现同一功能的多个模块统一起来标识,这样一来更容易后期的维护,系统结构更加清晰。或者归纳为:便于分层设计、利于系统抽象、降低耦合度以及使接口与实现分开。

     

    六、函数指针数组
    例:char * (*pf[3])(char *)
    函数指针数组本质是一个数组,这里pf就是数组名;
    该数组有3个元素pf[0]、pf[1]、pf[2],分别存放了3个函数指针;
    指向的3个函数的返回值都是 char *,形参都是 char *;
    程序示例:
    # include <stdio.h>
    void fun1(char * p)
    {
    printf("%s ", p);
    }
    void fun2(char * p)
    {
    printf("%s ", p);
    }
    void fun3(char * p)
    {
    printf("%s ", p);
    }
    int main()
    {
    void (*pf[3])(char *); //定义函数指针数组
    pf[0] = fun1;
    pf[1] = fun2;
    pf[2] = fun3;
    pf[0]("fun1"); //形参为字符串"fun1",传递给形参字符串首地址
    pf[0]("fun2");
    pf[0]("fun3");
    return 0;
    }

     

    七、函数指针数组指针
    例 char * (*(*pf)[3])(char * p);
    函数指针数组指针本质是一个指针;
    该指针指向一个数组;
    该数组里面存放的都是指向函数的指针;
    程序示例:
    #include <stdio.h>
    #include <string.h>

    char * fun1(char * p)
    {
    printf("%s ",p);
    return p;
    }

    char * fun2(char * p)
    {
    printf("%s ",p);
    return p;
    }

    char * fun3(char * p)
    {
    printf("%s ",p);
    return p;
    }

    int main()
    {
    char * (*a[3])(char * p);
    char * (*(*pf)[3])(char * p);
    pf = &a;

    a[0] = fun1;
    a[1] = &fun2;
    a[2] = &fun3;

    pf[0][0]("fun1");
    pf[0][1]("fun2");
    pf[0][2]("fun3");
    return 0;
    }



  • 相关阅读:
    DButils工具类能够用来获取数据库连接向数据库插入更新删除对象
    Android 实现ActionBar定制
    查看CentOs6.5/7的系统版本号
    安装Was liberty之步骤
    在centOS上安装VNC
    SCP远程拷贝命令
    Was liberty资料总结
    罗杰斯:做你喜欢的工作,你会变成个有钱人
    【Java/csv】一个CSV文件解析类(转载)
    当你的才华还撑不起你的野心时,那你就应该静下心来学习。
  • 原文地址:https://www.cnblogs.com/shuaishuaidefeizhu/p/5882654.html
Copyright © 2020-2023  润新知