指针和函数的关系

  1. 函数指针(指向函数的指针)

            一个函数在编译之后,会占据一部分内存,而它的函数名,就是这段函数的首地址。

    可以把一个指针声明成为一个指向函数的指针。

            C 语言规定函数名会被转换为指向这个函数的指针,除非这个函数名作为 & 操作符或 sizeof 操作符的操作数(注意:函数名用于 sizeof 的操作数是非法的)。也就是说 f = test; 中 test 被自动转换为 &test,而 f = &test; 中已经显示使用了 &test,所以 test 就不会再发生转换了。因此直接引用函数名等效于在函数名上应用 & 运算符,两种方法都会得到指向该函数的指针。
     示例1

    int fun1(int,int);
    int fun1(int a, int b){ 
        return a+b;
    }
    int main(){
        int (*pfun1)(int,int); /函数指针包含参数类型
        pfun1=fun1;//这里&fun1和fun1的值和类型都一样,用哪个无所谓 
        int a=(*pfun1)(5,7); //通过函数指针调用函数。
    }

            函数名 test,是一个符号用来标识一个函数的入口地址,在使用中函数名会被转换为指向这个函数的指针,指针的值就是函数的入口地址,&test 在前面已经说了:显示获取函数的地址。*test 可以认为由于 test 已经被转换成了函数指针, 指向这个函数,所以 *test 就是取这个指针所指向的函数名,而又根据函数名会被转换指向该函数的指针的规则,这个函数也转变成了一个指针,所以 *test 最终也是一个指向函数 test 的指针。也就是说:*test --> *(&test) --> test --> &test。上述关系十分重要!
    示例1的补充

    #include <stdio.h>
    int fun1(int,int);
    int fun1(int a, int b){
        return a+b;
    }
    /* 要调用上面定义函数的主函数 */
    int main (){
        int (*pfun1)(int,int);
        pfun1=fun1;//这里&fun1和fun1的值和类型都一样,用哪个无所谓
        int a=(*pfun1)(5,7); //通过函数指针调用函数。
        printf("%d
    ",a);
        int e = fun1(5,7);
        printf("%d
    ",e);
        int b = (&fun1)(5,7);
        printf("%d
    ",b);
        int c = (*fun1)(5,7);
        printf("%d",c);
        return 0;
    }
    //根据关系 *fun1==*&fun1==fun1==&fun1 可知,以上的运行结果会得到4个5+7。

    函数指针一个调用形式,另外三种函数调用形式

  2. 指针函数(返回值为指针的函数)
    所谓指针函数,就是返回指针的函数,C语言的库函数中有很多都是指针函数
    函数的返回值不仅仅局限于指向变量的指针,也可以是指向函数的指针
    int* pfun1(int,int); //不带括号就表示返回值是指针
    

      

  3. 两者混用(不常用)
    首先来看这个声明:*int (*function(int)) (double*, char); 要了解此声明的含义,首先来看 function(int),将 function 声明为一个函数,它带有一个 int 型的形式参数,这个函数的返回值为一个指针,正是函数指针 int (*) (double*, char); 这个指针指向一个函数,此函数返回 int 型并带有两个分别是 double* 型和 char 型的形参(绕的很)。

  4. 函数指针数组
    假设现在有一个文件处理程序,通过一个菜单按钮来选择相应的操作(打开文件,读文件,写文件,关闭文件)。这些操作都实现为函数且类型相同,分别为:
    void open();
    void read();
    void write();
    void close();

    现在定义一个函数指针类型的别名PF:

    typedef void (*PF) ( );

    把以上4种操作取地址放入一个数组中,得到:

    PF file_options[ ] = {
        &open,
        &read,
        &write,
        &close
    };

    如果不使用 typedef,那么分析起来就会比较复杂,结果是 void (*file_options[ ]) ( );

    这个数组中的元素都是指向不接受参数且不返回任何值的函数的指针,因此这是一个函数指针数组。



  5. 函数与指针的复杂声明(不做要求,一般用typedef代替它)
    int *(*(*fp)(int)) [10];

    阅读步骤:

    1.从未定义的变量名开始阅读 -------------------------------------------- fp
    2.往右看,什么也没有,遇到了),因此往左看,遇到一个* ------ 一个指向某对象的指针
    3.跳出括号,遇到了(int) ----------------------------------- 一个带一个int参数的函数
    4.向左看,发现一个* --------------------------------------- (函数)返回一个指向某对象的指针
    5.跳出括号,向右看,遇到[10] ------------------------------ 一个10元素的数组
    6.向左看,发现一个* --------------------------------------- 一个指向某对象指针
    7.向左看,发现int ----------------------------------------- int类型

    所以 fp 是指向函数的指针(函数指针), 该函数返回一个指向数组的指针,此数组有 10 个 int* 型的元素。

    int *(*(*fp)(int)) [10]; (*fp)(int)是一个指向函数的指针ptr*(*fp)(int)相当于一个指针ptr1(指针函数的返回值)最后剩下int *ptr1[10],可以理解。



原文地址:https://www.cnblogs.com/baconZhang/p/13816225.html