二十一天学通C语言:函数型指针

时间:2022-12-09 01:33:05
二十一天学通C语言:函数型指针
本文节选自《21天学通C语言》一书

    C程序中的函数也都是存放在代码区内的,它们同样也是有地址的。那么如何取得函数的地址呢?在前面也说过函数定义的时候实际上是定义了一个函数变量,那么是否可以将函数变量赋值给其他变量呢?回答这些问题需要涉及另外一个概念:函数型指针。按照已有的指针的知识,顾名思义,函数型指针就是指向函数的指针。如果有一个函数声明为:
int func(const int a, const int b);
    那么,此时声明的函数变量add的地址即为这个函数的地址,同时,add的值保存为这个函数的地址,这个特性与数组相似:数组变量与数组变量的地址均为数组的起始地址。而在这个函数声明中,函数类型为int (const int a, const int b)。使用该函数类型来定义一个函数型指针,其方式如下:
int (* fp)(const int a, const int b);    /* 其中,参数列表的参数名a和b可省 */
    上述语句将变量func定义为指向类型为int (const int a, const int b)的指针操作符和变量名两侧的小括号不可省,否则其含义大不相同。例如:
int * fp(const int a, const int b);
    此时,指针操作符与数据类型int结合为int型指针类型,该语句只是声明了一个fp函数,而非定义一个函数指针。为该函数型指针赋值的方式如下:
fp = func;
被赋值的函数变量的类型必须与fp的类型完全一致,包括其返回类型和每一个形参的类型。否则程序将报错。
    注意:函数型指针变量赋值时,左值与右值的类型必须完全一致。
使用函数型指针变量调用函数的方法与使用函数变量类似,得到函数地址后再带上参数列表即可。可以使用下面两种方式来调用函数:
fp(5, 6);

(*fp)(5, 6);
由于fp被赋值为函数变量func的地址,而func的值又等于其地址,所以*fp可以得到func函数的地址。因此,在调用方式上,可以粗略地将两者视为一致(实际上其后台的处理略有不同)。范例14-7演示了如何使用函数型指针来调用函数。
【范例14-7】使用函数型指针来调用函数,实现方法如示例代码14-7所示。
示例代码14-7
01    #include <stdio.h>
02    
03    int add(const int a, const int b) {            /* 定义add函数 */
04        return a + b;
05    }
06    
07    int main(void) {
08        int (*fp) (const int a, const int b);        /* 定义函数指针 */
09    
10        fp = add;                                /* 将其赋值为add */
11        printf("3 + 4 = %d/n", fp(3, 4));            /* 使用fp计算+ 4的值 */
12        printf("3 + 4 = %d/n", (*fp)(3, 4));        /* 使用*fp计算+ 4的值 */
13    
14        printf("%p/n", add);                        /* 输出add的值 */
15        printf("%p/n", &add);                        /* 输出add的地址 */
16        printf("%p/n", fp);                        /* 输出fp的值 */
17        printf("%p/n", *fp);                        /* 输出fp指向的值 */
18    
19        return 0;
20    }
【运行结果】程序运行后。
 【代码解析】本程序定义了一个函数指针,并将其赋值为相应类型的函数变量add。
    第11~12行分别使用fp和*fp的方式调用函数,从图14-12的第1~2行中可以看到它们的调用结果是一样的。
    第14~17行输出了add的值和地址、fp的值和指向的值,从图14-12的第3~6行中可以看到它们的调用结果都是一样的。