C语言、C++编程技术馆

C语言,C++编程,C语言开发应用,C++开发应用,VC++编程, C++Builder编程,C语言教程,C++教程,C语言开发教程,C++开发教程,VC++教程, C++Builder教程,C++培训,C语言培训,编程培训
随笔 - 28, 文章 - 0, 评论 - 1, 阅读 - 39802
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

C/C++中函数指针的含义

Posted on   teiller2008  阅读(257)  评论(0编辑  收藏  举报

   函数存放在内存的代码区域内,它们同样有地址,我们如何能获得函数的地址呢?

      如果我们有一个int test(int a)的函数,那么,它的地址就是函数的名字,这一点如同数组一样,数组的名字就是数组的起始地址。

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

    int (*fp)(int a);//这里就定义了一个指向函数的指针

      函数指针不能绝对不能指向不同类型,或者是带不同形参的函数,在定义函数指针的时候我们很容易犯如下的错误。

    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();
    }

96堆栈 软件编程网http://www.96dz.com,上面有很多编程教学的视频教程下载。C++视频教程、C#视频教程、Java视频教程下载。

编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
点击右上角即可分享
微信分享提示