【C语言】函数指针

函数指针的声明

typedef int (*fun_ptr)(int,int); // 声明一个指向同样参数、返回值的函数指针类型

实例1

#include <stdio.h>


typedef int (*fun_t)(int, int);


int sum(int num1, int num2)
{
    return num1 + num2;
}


int main()
{
    fun_t p;
    p = sum;
    int a = 3;
    int b= -4;
    printf("%d\n", p(a, b));
}

实例2

#include <stdio.h>


int max(int num1, int num2)
{
    return num1 + num2;
}


int main()
{
    int (*p)(int, int);
    p = max;
    int a = 3;
    int b= -4;
    printf("%d\n", p(a, b));
}

函数指针数组

#include <stdio.h>


typedef int (*fun_t)(int, int);


int sum(int num1, int num2)
{
    return num1 + num2;
}


int max(int num1, int num2)
{
    return num1 > num2 ? num1 : num2;
}


int main()
{
    fun_t p[2];
    p[0] = sum;
    p[1] = max;
    int a = 3;
    int b= -4;
    printf("%d\n", p[0](a, b));
    printf("%d\n", p[1](a, b));
}

对比实例1与实例2,发现实例1是用typedef来定义一个函数指针类型,然后在主函数中定义该函数指针类型的指针变量;而实例2是直接定义一个函数指针。在这里可以分析一下函数指针与指针的关系。

  1. int p(int, int);从p开始,p先与()结合,说明p是一个函数,有2个int类型的函数形式参数,然后与左边的int结合,说明该函数返回的是int类型的数据。
  2. int (*p)(int, int);从p开始,p先与*结合,说明p是一个指针,接着与()结合,说明指针指向的是一个函数,然后再与最右边()里的结合, 说明函数有2个int型的参数, 再与最左边的int结合, 说明该函数返回的是int类型的数据, 所以p是一个指向有2个int类型参数且返回类型为int型的函数的指针。
  3. int (*p(int, int))[4];从p开始,p先与()结合,说明p是一个函数,有2个int类型的函数形式参数,然后与p左边的*结合,说明函数返回的是一个指针,然后与[]结合,说明指针指向的一个数组,数组的元素有4个,然后与int结合,说明数组的元素是int类型的数据,所以p是一个参数为2个int类型的数据且返回一个由4个int类型的数据组成的数组的指针变量的函数。
    实例3
    将一个二维数组的每个元素都偏移num
int  (*func(int num))[4]
{
    static int buff[3][4] = {0};

    for(int i = 0, j = 0; i < 3; i++)
        for(j = 0; j < 4; j++)
            *(*(buff + i) + j) += num;
    return buff;
}

一般用typedef来定义新类型,这样方便理解

typedef int (*arr)[4];

arr func(int num)
{
    static int buff[3][4] = {0};
    for(int i = 0, j = 0; i < 3; i++)
        for(j = 0; j < 4; j++)
            *(*(buff + i) + j) += num;
    return buff;
}
  1. int (*(*p)(int, int))[4]从p开始,p先与*结合,说明p是一个指针,然后与()结合,说明指针指向的是一个函数,同时函数有2个int类型的参数,然后与*结合,说明函数返回的是一个指针,然后与[]结合,说明指针指向的是一个数组,元素个数为4,然后与int结合数组的元素类型是int,所以p是一个指向有2个int类型的参数且返回一个指向由4个int类型数据组成的数组的指针的函数。

  2. int *(*p(int, int))[4];从p开始,p先与()结合,说明p是一个函数,有2个int类型的函数形式参数,然后与p左边的*结合,说明函数返回的是一个指针,然后与[]结合,说明指针指向的一个数组,数组的元素有4个,然后与*结合,说明数组元素的类型是指针,然后与int结合,说明指针指向的是int类型的数据,所以p是一个参数为2个int类型的数据且返回一个指向由int类型指针变量组成的数组的指针变量的函数。

C 语言规定函数名会被转换为指向这个函数的指针

#include <stdio.h>


typedef int (*fun_t)(int, int);


int sum(int num1, int num2)
{
    return num1 + num2;
}


int main()
{
    fun_t p;
    p = sum;
    int a = 3;
    int b= -4;
    printf("p(a, b) = %d\n", p(a, b));
    printf("*p(a, b) = %d\n", (*p)(a, b));
    printf("(*(&p))(a, b) = %d\n", (*(&p))(a, b));
    printf("sum(a, b) = %d\n", sum(a, b));
    printf("*sum(a, b) = %d\n", (*sum)(a, b));
    printf("%p\n", sum);
    printf("%p\n", &sum);
    printf("%p\n", *sum);
}

/*
输出结果
p(a, b) = -1
*p(a, b) = -1
(*(&p))(a, b) = -1
sum(a, b) = -1
*sum(a, b) = -1
0000000000401550
0000000000401550
0000000000401550
*/

这里的玄学就是 *sum为什么能和上面两个之前介绍过的输出一样的值。
首先来看函数名 sum,是一个符号用来标识一个函数的入口地址,在使用中函数名会被转换为指向这个函数的指针,指针的值就是函数的入口地址,&sum:显示获取函数的地址。*sum可以认为由于 sum已经被转换成了函数指针, 指向这个函数,所以 *sum就是取这个指针所指向的函数名,而又根据函数名会被转换指向该函数的指针的规则,这个函数也转变成了一个指针,所以 *sum最终也是一个指向函数 sum的指针。也就是说:*sum–> *(&sum) --> sum–> &sum。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值