函数指针与函数指针数组讲解

函数指针

函数指针指的就是指向函数的指针,表示形式为void (*)(),其中第一个括号中放的是指针变量,第二个括号放的是参数的类型和数目,如若某函数形参变量是int Add(int a,int b),那么就是int(*pf)(int,int),编译器定义int(pf)(int,int)的形式也同样成立。

其中函数的地址传址加不加取地址符都是可以的,如int(*pf)(int,int)=Add; 或 int(*pf)(int,int)=&Add;

那么我们如何应用呢,下面有两个简单的示例:

int Add(int x,int y){
    return x+y;
}
int main(){
    int arr[10];
    int(*p)[10]=&arr;
    int(*pf)(int,int)=&Add;
    int ret=(*pf)(3,4);
    retuen 0;
}
int test(char*str){}
int main(){
    int (*pf)(char*)=test;
    int ret=(*pf)(3);
    printf("%d",ret);
    return 0;
}

其中拓展一个知识点,函数指针也算是一种类型所以也可以强制类型转换,如void(*)()是函数指针的形式,那么(void(*)())0就是将0强制转换成void的函数指针。


了解了这两个知识点后,下面我们看一个表达式:

void(*signal(int,void(*)(int))(int)

这个表达式相对复杂,我们可以由内而外的来解析:

最内层表达式void(*)(int),很明显这是我们讲过的函数指针,指向一个void类型形参int类型的函数指针。

第二层表达式signal(int,void(*)(int)),这是一个函数调用,signal函数的参数是一个int类型和函数指针。

最外层表达式void(*signal(int,void(*)(int))(int),可以看出这是一个函数指针,也是void(*)()的形式,去掉参数就是void(*)(int),所以它的函数指针变量就是signal(int,void(*)(int))。

面对这样复杂的表达式的可读性并不高,所以一般我们需要将它简化:

typedef void(*)(int) pf_t;

void(*signal(int,void(*)(int))(int)=pf_t signal(int,pf_t);

我们将void(*)(int)重定义成pf_t,是表达式清晰,可读性变高。 


函数指针数组

函数指针数组顾名思义就是存放函数指针的数组,它的好处就是减少了很大一部分的代码量。比如我们要用函数指针来指向不同的函数,那么我们就要一个个的写,函数指针数组就将这些指针放在了一个数组中,经过循环后即可使用。

表示形式:

int(*pf[3])(int,int)={Add,Sub,Mul};

其中[3]指的是数组中一共有三个函数指针,类型都是(int,int),这也反映了该数组的一个限制性就是只能包含参数类型相同的函数。

下面我们看一下它的简单的应用:

int Add(int x,int y){
    return x+y;
}
int sub(int x,int y){
    return x-y;
}
int Mul(int x,int y){
    return x*y;
}
int Div(int x,int y){
    return x/y;
}
int main(){
    int x,y,input;
    printf("请选择:");
    scanf("%d",&input);
    printf("请输入两个操作数:");
    scanf("%d %d",&x,&y);
    int(*pf[4])(int,int)={0,Add,Sub,Mul,Div};
    int ret=(*pf[input])(x,y);
    printf("%d",ret);
    return 0;
}
    

这个代码实现了一个简易的计算器原理,而主函数也减少了函数的调用语句,如果我们给计算器加上菜单,那么main函数中就要用switch语句,这时函数指针数组就起到了作用。


int Add(int x,int y){
    return x+y;
}
int Sub(int x,int y){
    return x-y;
}
int Mul(int x,int y){
    return x*y;
}
int Div(int x,int y){
    return x/y;
}
void menu(){
    printf("************\n");
    printf("1.相加\n");
    printf("2.相减\n");
    printf("3.相乘\n");
    printf("4.相除\n");
    printf("************\n");
}
int main(){
    int x=0,y=0,ret=0,input;
    int (*pfArr[5])(int,int)={0,Add,Sub,Mul,Div};
    do{
        menu();
        printf("请选择:");
        scanf("%d",&input);
        if(input==0)
            printf("退出\n");
        else if(input>=1&&input<=4){
            printf("请输入两个操作数:");
            scanf("%d %d",&x,&y);
            ret=(*pfArr[input])(x,y);
            printf("ret=%d",ret);
        }
    }
}

由此可见,我们将原本的switch语句简化成了ret=(*pf[input])(x,y)语句,减少了代码量。


指向函数指针数组的指针

通过上面的学习我们知道函数数组指针的表示形式为:

int(*pf[4])(int,int)={0,Add,Sub,Mul,Div}

那么顾名思义指向函数指针数组的指针就是将函数指针数组的整个数组的地址传过去, 然后指针指向它,表示形式为:

int(*(*p)[4])(int,int)=&pf

其中内部的int(*p)[4]是数组指针,外部是int(*)(int,int)。说明p是一个指针,指向一个大小为4的存放函数指针的数组。 

那么它的应用方式为如下示例:

int (*pf[4])(int,int)={0,Add,Sub,Mul,Div};
int (*(*p)[4])(int,int)=&pf;
for(int i=0;i<4;i++){
    p[i](3,4);
}

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

妮妮妮妮没事吧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值