c/c++函数指针(3)

2022年01月15日 阅读数:4
这篇文章主要向大家介绍c/c++函数指针(3),主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

学习要点:ios

        1,函数地址的通常定义和typedef简化定义;c++

        2,函数地址的获取;编程

        3,A函数地址做为B函数参数的传递;数组

    函数存放在内存的代码区域内,它们一样有地址.若是咱们有一个int test(int a)的函数,那么,它的地址就是函数的名字,这一点如同ide

数组同样,数组的名字就是数组的起始地址。函数

    定义一个指向函数的指针用以下的形式,以上面的test()为例:学习

    int (*fp)(int a);//这里就定义了一个指向函数(这个函数的参数仅仅为一个int类型)的指针spa

    通常定义方式:指针

    data_types (*func_pointer)( data_types arg1, data_types arg2, ...,data_types argn);教程

    函数指针不能绝对不能指向不一样类型,或者是带不一样形参的函数,这点尤为注意.

    在定义函数指针的时候咱们很容易犯以下的错误:

    int *fp(int a);//这里是错误的,由于按照结合性和优先级来看就是先和()结合,而后变成了一个返回整形指针的函数了,而不是函数指针.

    下面咱们来看一个具体的例子:

    #include <iostream>

    #include <string>

    using namespace std;


    int test(int a);


    void main(int argc,char* argv[])   

    {

        cout<<test<<endl;//显示函数地址

        int (*fp)(int a);

        fp=test;//将函数test的地址赋给函数学指针fp

        cout<<fp(5)<<"|"<<(*fp)(10)<<endl;

        //上面的输出fp(5),这是标准c++的写法,(*fp)(10)这是兼容c语言的标准写法,两种赞成,但注意区分,避免写的程序产生移植性问题!

        cin.get();

    }


    int test(int a)

    {

        return a;

    }


    typedef定义能够简化函数指针的定义,在定义一个的时候感受不出来,但定义多了就知道方便了,上面的代码改写成以下的形式:

    #include <iostream>

    #include <string>

    using namespace std;


    int test(int a);


    void main(int argc,char* argv[])   

    {

        cout<<test<<endl;

        typedef int (*fp)(int a);//注意,这里不是生命函数指针,而是定义一个函数指针的类型,这个类型是本身定义的,类型名为fp

        fp fpi;//这里利用本身定义的类型名fp定义了一个fpi的函数指针!

        fpi=test;

        cout<<fpi(5)<<"|"<<(*fpi)(10)<<endl;

        cin.get();

    }


    int test(int a)

    {

        return a;

    } 


    函数指针一样是能够做为参数传递给函数的,下面咱们看个例子,仔细阅读你将会发现它的用处,稍加推理能够很方便使咱们进行一些复杂的编程工做。

    //-------------------该例以上一个例子做为基础稍加了修改-----------------------------

    #include <iostream>   

    #include <string>   

    using namespace std;   


    int test(int);   


    int test2(int (*ra)(int),int);


    void main(int argc,char* argv[])     

    {   

        cout<<test<<endl;

        typedef int (*fp)(int);   

        fp fpi;

        fpi=test;//fpi赋予test 函数的内存地址


        cout<<test2(fpi,1)<<endl;//这里调用test2函数的时候,这里把fpi所存储的函数地址(test的函数地址)传递了给test2的第一个形参

        cin.get();

    }   


    int test(int a)

    {   

        return a-1;

    }


    int test2(int (*ra)(int),int b)//这里定义了一个名字为ra的函数指针

    {

        int c=ra(10)+b;//在调用以后,ra已经指向fpi所指向的函数地址即test函数

        return c;

    }


    利用函数指针,咱们能够构成指针数组,更明确点的说法是构成指向函数的指针数组,这么说可能就容易理解的多了。

    #include <iostream>   

    #include <string>   

    using namespace std;


    void t1(){cout<<"test1";}

    void t2(){cout<<"test2";}

    void t3(){cout<<"test3";}

    void main(int argc,char* argv[])     

    {

        void* a[]={t1,t2,t3};

        cout<<"比较t1()的内存地址和数组a[0]所存储的地址是否一致"<<t1<<"|"<<a[0]<<endl;


        cout<<a[0]();//错误!指针数组是不能利用数组下标操做调用函数的


        typedef void (*fp)();//自定义一个函数指针类型

        fp b[]={t1,t2,t3}; //利用自定义类型fp把b[]定义趁一个指向函数的指针数组

        b[0]();//如今利用指向函数的指针数组进行下标操做就能够进行函数的间接调用了;

        cin.get();

    }


    仔细看上面的例子可能不用我多说你们也会知道是怎么一会事情了,最后咱们作一个重点小结,只要记住这一点,对于理解利用函数指针构成数组进行函数间接调用就很容易了!

    void* a[]={t1,t2,t3};

    cout<<"比较t1()的内存地址和数组a[0]所存储的地址是否一致"<<t1<<"|"<<a[0]<<endl;


    cout<<a[0]();//错误!指针数组是不能利用数组下标操做调用函数的


    上面的这一小段中的错误行,为何不能这么调用呢?


    前一篇教程咱们已经说的很清楚了,不过在这里咱们仍是复习一下概念,指针数组元素所保存的只是一个内存地址,既然只是个内存地址就

不可能进行a[0]()这样地址带括号的操做,而函数指针不一样它是一个例外,函数指针只因此这么叫它就是由于它是指向函数指向内存的代码区的指针

,它被系统授予容许与()括号操做的权利,进行间接的函数调用,既然函数指针容许这么操做,那么被定义成函数指针的数组就必定是能够同样的操做的。


    对上一例子改动:

    //a.c

    #include <iostream>

    #include <string>

    using namespace std;


    void t1(){cout<<"test1\n";}

    void t2(){cout<<"test2\n";}

    void t3(){cout<<"test3\n";}


    int main(int argc,char* argv[])

    {

            void* a[3];

            a[0]=(void *)t1;

            a[1]=(void *)t2;

            a[2]=(void *)t3;

            printf("t1=0x%x\n",*t1);

            cout<<"比较t1()的内存地址和数组a[0]所存储的地址是否一致"<<t1<<"|"<<a[0]<<endl;

    //      cout<<a[0]();//错误!指针数组是不能利用数组下标操做调用函数的

            typedef void (*fp)();//自定义一个函数指针类型

            fp b[]={t1,t2,t3}; //利用自定义类型fp把b[]定义趁一个指向函数的指针数组

            b[0]();//如今利用指向函数的指针数组进行下标操做就能够进行函数的间接调用了;

            cin.get();

            return 0;

    }


    编译:

    [root@CHN ]# g++ a.c -o a

    a.c: In function `int main(int, char**)':

    a.c:16: warning: the address of `void t1()', will always be `true'

    [root@CHN ]# ./a

    t1=0x804881c

    比较t1()的内存地址和数组a[0]所存储的地址是否一致1|0x804881c

    test1


root