当前位置:  编程技术>c/c++/嵌入式

函数指针与指针函数的学习总结

    来源: 互联网  发布时间:2014-10-18

    本文导语:  函数指针是指向函数的指针,指针函数是指一个函数的返回值是一个指针,但下面的几道题还是感觉很迷惑。各位能否讲的详细点呢?(1) float(**def)[10]   def是什么?(2) double*(*gh)[10]   gh是什么?(3) double(*f[10])()   f是什么?(4) ...

函数指针是指向函数的指针,指针函数是指一个函数的返回值是一个指针,但下面的几道题还是感觉很迷惑。各位能否讲的详细点呢?

(1) float(**def)[10]   def是什么?
(2) double*(*gh)[10]   gh是什么?
(3) double(*f[10])()   f是什么?
(4) int*((*b)[10])    b是什么?这样老感觉有点乱,有什么窍门可以记得并理解的清楚一点么?

======================
解答:
  
(1) def是一个指针, 指向的对象也是一个指针, 指向的指针最终指向的是10个float构成的数组.

(2) gh是指针, 指向的是10个元素构成的数组, 数组的元素是double*类型的指针.

(3) f是10个元素构成的数组, 每个元素是指针, 指针指向的是函数, 函数类型为无参数且返回值为double. 下面要讲的窍门的例子跟这个很类似.

(4) b是指针,指向的是10个元素构成的数组, 数组元素为int*类型的指针.

窍门如下:
如果我们碰到复杂的类型声明,该如何解析它?例如:
char (*a[3])(int);
a到底被声明为什么东东?指针?数组?还是函数?

分析时,从a 最接近(按运算符优先级)处开始。我们看到a最接近符号是[ ]——注意:*比[ ]的优先级低。a后既然有[ ],那么a是数组,而且是包含3个元素的数组。

那这个数组的每个元素是什么类型呢?虽然数组a只含有a[0]、a[1]、a[2]三个元素,a[3]实际上已经越界,但在分析数组a的元素的类型时,我们正好需要形式上的元素a[3]。知道了a[3]的类型,就知道了a的元素的类型。 a[3]是什么类型?是指针,因为它的前面有*. 由此可知,数组a的元素是指针。

光说是指针还不够。对于指针,必须说出它指向的东东是什么类型。它指向的东东是什么,就看*a[3]是什么(a[3]是指针,它指向的东东当然是*a[3])了。继续按优先级观察,我们看到*a[3]后面有小括号,所以可以肯定*a[3]是函数。即数组a的元素是指向函数的指针。

指向的是什么类型的函数?这很明显,是入参为int、返回值为char的类型的函数。
至此解析完毕。
按上述方法,再复杂的也可以一步步解析出来。

就像习武不是为了打人而是为了防身一样,我们了解上述方法是为了看懂别人写的复杂声明,而不是为了在实践中自己去构造这种复杂的东东。实在需要复杂声明时,可以用typedef替代一部分。例如上面语句可改成两句:
typedef char (*FUN_PTR)(int);
FUN_PTR a[3];
这样就清晰多了。
此外,上面的分析方法还让我们对某些东西的本质更加清楚。比如,n维数组的本质都是一维数组。看个具体的例子:
int a[3][5];
这句声明的是一个包含3个元素的一维数组,其每个元素又是一个由5个int数构成的数组。我们不能理解为:a是一个包含5个元素的一维数组,其每个元素又是一个由3个int数构成的数组。为什么?还是按上面的方法分析,这里从略。

有的书上或网上提供"向右看,向左看"的方法, 其实缺乏通用性, 比如它不适用于对多维数组本质的分析. 而且这种方法掩盖了本质. 本质应该是按上面所讲的,根据运算符优先级逐层剥开.

  ==============================================================================
 
一、指针函数
当一个函数声明其返回值为一个指针时,实际上就是返回一个地址给调用函数,以用于需要指针或地址的表达式中。
格式:
类型说明符 * 函数名(参数)
当然了,由于返回的是一个地址,所以类型说明符一般都是int。
例如:int *GetDate();
      int * aaa(int,int);
函数返回的是一个地址值,经常使用在返回数组的某一元素地址上。

代码如下:

        int * GetDate(int wk,int dy);
        main()
        {
            int wk,dy;
            do
            {
                printf(Enter week(1-5)day(1-7)/n);
                scanf(%d%d,&wk,&dy);
            }
            while(wk5||dy7);
            printf(%d/n,*GetDate(wk,dy));
        }

        int * GetDate(int wk,int dy)
        {
            static int calendar[5][7]=
            {
               {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}
            };
            return &calendar[wk-1][dy-1];
        }

       
程序应该是很好理解的,子函数返回的是数组某元素的地址。输出的是这个地址里的值。

二、函数指针
指向函数的指针包含了函数的地址,可以通过它来调用函数。声明格式如下:
类型说明符 (*函数名)(参数)
其实这里不能称为函数名,应该叫做指针的变量名。这个特殊的指针指向一个返回整型值的函数。指针的声明必须和它指向函数的声明保持一致。
指针名和指针运算符外面的括号改变了默认的运算符优先级。如果没有圆括号,就变成了一个返回整型指针的函数的原型声明。
例如:
    void (*fptr)();
把函数的地址赋值给函数指针,可以采用下面两种形式:
        fptr=&Function;
        fptr=Function;
取地址运算符&不是必需的,因为单单一个函数标识符就标号表示了它的地址,如果是函数调用,还必须包含一个圆括号括起来的参数表。
可以采用如下两种方式来通过指针调用函数:
        x=(*fptr)();
        x=fptr();
第二种格式看上去和函数调用无异。但是有些程序员倾向于使用第一种格式,因为它明确指出是通过指针而非函数名来调用函数的。下面举一个例子:

代码如下:

        void (*funcp)();
        void FileFunc(),EditFunc();
        main()
        {
            funcp=FileFunc;
            (*funcp)();
            funcp=EditFunc;
            (*funcp)();
        }

        void FileFunc()
        {
            printf("FileFunc/n");
        }

        void EditFunc()
        {
            printf("EditFunc/n");
        }


程序输出为:
    FileFunc
    EditFunc

三、指针的指针
指针的指针看上去有些令人费解。它们的声明有两个星号。例如:
        char ** cp;
如果有三个星号,那就是指针的指针的指针,四个星号就是指针的指针的指针的指针,依次类推。
当你熟悉了简单的例子以后,就可以应付复杂的情况了。当然,实际程序中,一般也只用到二级指针,三个星号不常见,更别说四个星号了。
指针的指针需要用到指针的地址。
        char c='A';
        char *p=&c;
        char **cp=&p;
通过指针的指针,不仅可以访问它指向的指针,还可以访问它指向的指针所指向的数据。下面就是几个这样的例子:
        char *p1=*cp;   // (&c)
        char c1=**cp;
你可能想知道这样的结构有什么用?利用指针的指针可以允许被调用函数修改局部指针变量和处理指针数组。

代码如下:

        void FindCredit(int **);
        main()
        {
            int vals[]={7,6,5,-4,3,2,1,0};
            int *fp=vals;
            FindCredit(&fp);
            printf(%d/n,*fp);
        }

        void FindCredit(int ** fpp)
        {
            while(**fpp!=0)
            if(**fpp


    
 
 

您可能感兴趣的文章:

  • 深入解析函数指针与返回函数的指针
  • 指向类成员函数的指针其实并非指针
  • 请问如何根据函数指针打印出这个函数的名称?
  • c++函数指针和回调函数示例
  • 利用函数指针的好处是什么?
  • JAVA中函数调用时,能不能向 C/C++一样函数的入口参数可以为传出值(就是引用,或指针)
  • C:函数指针
  • 一般函数指针和类的成员函数指针深入解析
  • 一个线程函数如何取得GTK界面的所有控件指针?
  • 函数指针的一些概念详解
  • 系统函数返回的指针指向的内存释放的问题
  • sp->callback或snmp_callback函数指针在哪里赋值?
  • 函数指针的强制类型转换实现代码
  • 函数指针的问题
  • 有些系统函数返回一个数据指针,实际的内存占用空间应该在那里??
  • C#委托所蕴含的函数指针概念详细解析
  • C++中返回指向函数的指针示例
  • 请问return语句会执行哪些操作?在函数中return一个已分配内存的指针,该指针所占用的内存会释放吗?
  • C++普通函数指针与成员函数指针实例解析
  • 关于linux下多线程运行由同一函数指针传入不同函数体的问题
  • C# 静态构造函数使用总结
  • 类成员函数的重载、覆盖与隐藏之间的区别总结
  • .net获取日期时间函数总结
  • sql不常用函数总结以及事务,增加,删除触发器
  • 深入C++中构造函数、拷贝构造函数、赋值操作符、析构函数的调用过程总结
  • python中关于时间和日期函数的常用计算总结(time和datatime)
  • 深入C++拷贝构造函数的总结详解
  • 深入C++ string.find()函数的用法总结
  • C++中拷贝构造函数的总结详解
  • shell自定义函数的6个特点总结
  • 浅谈SQLite时间函数的使用说明与总结分析
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • C++ Maps 成员 key_comp():返回比较元素key的函数
  • 请问:定义了2个函数,其中第一个函数要访问另外一个函数的变量,怎么处理阿?谢谢
  • C++ Maps 成员 value_comp():返回比较元素value的函数
  • 如果知道一个函数的地址或函数名,如何得到函数所在的文件名?
  • C++ MultiMaps 成员 key_comp():返回比较key的函数
  • java的数学函数在那个类中,如幂函数、指数、对数、双曲线函数等?
  • C++ MultiMaps 成员 value_comp():返回比较元素value的函数
  • 一个父类的构造函数的参数是(Applet applet),请问它的子类构造函数当中应怎样调用父类构造函数?
  • C++ STL Bitsets构造函数及成员函数解释及代码示例
  • 虚函数被类的构造析构函数和成员函数调用虚函数的执行过程
  • C++ Strings(字符串) 成员 Constructors:构造函数,用于字符串初始化
  • 在内核的某个函数中,如何能知道是哪个用户空间的函数调用了它,以及这个用户空间函数所在的文件?
  • linux c 生成随机数srand函数和rand函数介绍及代码示例
  • 在dos下访问内存的MK_FP函数在linux下对应什么函数?int86()函数呢?
  • Linux下gettimeofday()函数和clock()函数:精确到毫秒级的时间
  • 一个静态库包含多个函数,应用程序连接了库中的某个函数,应用程序目标代码中是否还包含了该静态库中的其他函数代码?
  • Linux c++虚函数(virtual function)简单用法示例代码
  • Oracle 函数大全[字符串函数,数学函数,日期函数]第1/4页
  • sharepoint 2010 使用STSNavigate函数实现文件下载举例
  • js的众多函数令小弟实在搞不清楚!哪有函数速查手册之类的软件或者书籍!谢了!比如,setInterval、clearInterval这两个函数是干什么的?
  • cityhash 32位,64位和128位介绍及函数列表
  • 虚函数与纯虚函数(C++与Java虚函数的区别)的深入分析




  • 特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3