zoukankan      html  css  js  c++  java
  • 指针函数与函数指针的差别

    一、

    在学习arm过程中发现这“指针函数”与“函数指针”easy搞错,所以今天,我自己想一次把它搞清楚,找了一些资料。首先它们之间的定义:

    1、指针函数是指带指针的函数,即本质是一个函数。

    函数返回类型是某一类型的指针

         类型标识符    *函数名(參数表)

          int *f(x,y);

     

    首先它是一个函数,仅仅只是这个函数的返回值是一个地址值。函数返回值必须用同类型的指针变量来接受,也就是说。指针函数一定有函数返回值,并且。在主调函数中。函数返回值必须赋给同类型的指针变量。

    表示:

    float *fun();

    float *p;

    p = fun(a);

    注意指针函数与函数指针表示方法的不同,千万不要混淆。最简单的辨别方式就是看函数名前面的指针*号有没有被括号()包括,假设被包括就是函数指针。反之则是指针函数。

    来讲具体一些吧!

    请看以下

     指针函数:
        当一个函数声明其返回值为一个指针时,实际上就是返回一个地址给调用函数,以用于须要指针或地址的表达式中。
        格式:
             类型说明符 * 函数名(參数)
        当然了,因为返回的是一个地址,所以类型说明符一般都是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) );
                    scanf(%d%d,&wk,&dy);
                }
                while(wk<1||wk>5||dy<1||dy>7);
                printf(%d ,*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];
            }
            
    程序应该是非常好理解的,子函数返回的是数组某元素的地址。输出的是这个地址里的值。

     

     

     

    2、函数指针是指向函数的指针变量。即本质是一个指针变量。

     int (*f) (int x); /* 声明一个函数指针 */

     f=func; /* 将func函数的首地址赋给指针f */

     

    指向函数的指针包括了函数的地址,能够通过它来调用函数。声明格式例如以下:
            类型说明符 (*函数名)(參数)
        事实上这里不能称为函数名。应该叫做指针的变量名。

    这个特殊的指针指向一个返回整型值的函数。指针的声明笔削和它指向函数的声明保持一致。
            指针名和指针运算符外面的括号改变了默认的运算符优先级。假设没有圆括号。就变成了一个返回整型指针的函数的原型声明。


        比如:
            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 );
            }

            void EditFunc()
            {
                printf(EditFunc );
            }

            
    程序输出为:
                FileFunc
                EditFunc

     

    基本的差别是一个是指针变量,一个是函数。在使用是必要要搞清楚才干正确使用

     

    二、指针的指针
        指针的指针看上去有些令人费解。它们的声明有两个星号。比如:
            char ** cp;
        
    假设有三个星号,那就是指针的指针的指针,四个星号就是指针的指针的指针的指针,依次类推。当你熟悉了简单的样例以后,就能够应付复杂的情况了。当然,实际程序中,一般也仅仅用到  二级指针,三个星号不常见,更别说四个星号了。
        指针的指针须要用到指针的地址。
            char c='A';
            char *p=&c;
            char **cp=&p;
        
    通过指针的指针,不仅能够訪问它指向的指针,还能够訪问它指向的指针所指向的数据。

    以下就是几个这种样例:
            char *p1=*cp;
            char c1=**cp;
        
    你可能想知道这种结构有什么用。利用指针的指针能够同意被调用函数改动局部指针变量和处理指针数组。



            void FindCredit(int **);

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

            void FindCredit(int ** fpp)
            {
                while(**fpp!=0)
                if(**fpp<0) break;
                else (*fpp)++;
            }

        
    首先用一个数组的地址初始化指针fp,然后把该指针的地址作为实參传递给函数FindCredit()。

    FindCredit()函数通过表达式**fpp间接地得到数组中的数据。为遍历数组以找到一个负值,FindCredit()函数进行自增运算的对象是调用者的指向数组的指针,而不是它自己的指向调用者指针的指针。

    语句(*fpp)++就是对形參指针指向的指针进行自增运算的。可是由于*运算符高于++运算符,所以圆括号在这里是必须的,假设没有圆括号。那么++运算符将作用于二重指针fpp上。

    三、指向指针数组的指针
        指针的指针还有一使用方法旧处理指针数组。

    有些程序猿喜欢用指针数组来取代多维数组。一个常见的使用方法就是处理字符串。



            char *Names[]=
            {
                 Bill,
                 Sam,
                 Jim,
                 Paul,
                 Charles,
                 0
            };

            main()
            {
                char **nm=Names;
                while(*nm!=0) printf(%s ,*nm++);
            }

        
    先用字符型指针数组Names的地址来初始化指针nm。每次printf()的调用都首先传递指针nm指向的字符型指针。然后对nm进行自增运算使其指向数组的下一个元素(还是指针)。注意完毕上述觉得的语法为*nm++。它首先取得指针指向的内容,然后使指针自增。
        注意数组中的最后一个元素被初始化为0,while循环以次来推断是否到了数组末尾。

    具有零值的指针经常被用做循环数组的终止符。程序猿称零值指针为空指针(NULL)。採用空指针作为终止符,在树种增删元素时,就不必修改遍历数组的代码。由于此时数组仍然以空指针作为结束。

  • 相关阅读:
    Qt 最简单的多线程方法QtConcurrent::run()
    Qt 串口收发数据
    QString使用split按照某字符进行分解
    QT新建QWidget提示框(包含设置QLabel文字大小和居中)
    Mac电脑Docker拉取Mysql报错 no matching manifest for linux/arm64/v8 in the manifest list entries
    Goframe因为axios的header导致的一个BUG解析
    PHP版本如何写出让人很难理解的代码,显得自己很有水平
    vue通用配置异步加载同时保证同步
    GO性能分析pprof
    GO runtime的用法
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/5256728.html
Copyright © 2011-2022 走看看