记一次实验——复杂函数指针的调用

下午突然发愤决定搞定复杂指针的相关问题,看了几篇大大们的文章后,感觉略有收获。


个人的总结:从非保留字读起,如果有多个非保留字(如函数指针中的形参名,虽然这并没有必要),从最左边的读起。此后,如果遇到右括号,则向左读。如果遇到左括号,则向右读,读完所有括号后再按优先级分析一次。


我们来试一试,我会说的详细些。

int *(*(*func)(void *))[5];

只有一个非保留字func,从它读起

声明一个叫func的东西。

遇到右括号,向左读。

这个func是一个指针。

遇到左括号,向右读,跳过已经被分析的部分,遇到左括号,继续向右。

这个指针指向一个函数,函数接受void指针。

读到右括号,向左读。

函数返回一个指针。

此时所有的括号都分析完成,剩下的就很简单了。

[5]说明这个指针指向一个含有5个元素的数组。

*说明这个数组内的元素是指针。

最后int说明指针指向int数据类型。

最后总结:func是一个指向函数的指针,函数接受void指针,返回指向数组的指针,数组由5个int指针组成。



如果没晕的话,可以自行尝试下面的声明。答案可以用小刀用力刮开。

int (*(*func)[5])(void *);

func是一个指针,指向一个有5个元素的数组,每一个元素都是一个指向函数的指针,函数接受void型指针,返回一个int值。


声明理解的差不多了,那怎么调用呢?

#include<cstdio>
using namespace std;

int (*(*func)[5])(void *);
int a(void *pa){
    return 0;
}
int b(void *pb){
    return 1;
}
int c(void *pc){
    return 2;
}
int d(void *pd){
    return 3;
}
int e(void *pd){
    return 4;
}


int main()
{
    (*func)[0]=a;
    (*func)[1]=b;
    (*func)[2]=c;
    (*func)[3]=d;
    (*func)[4]=e;

    int *pn;
    int ans;
    int h=20;

    pn=&h;
    ans = (*func)[3]((int *)pn);
    printf("%d",ans);

    return 0;
}

既然func是一个指向数组的指针,那如果想操作数组内的元素,当然要先用"*"将func退成数组。

然后,再加上下标,同时用括号更改优先级,就变成了一个个指向函数的指针,我们再赋给它函数的地址,就能调用了


按照我的预期,它应该输出3。

不过呢,发现程序崩溃了。

debug发现程序连第一步都没走完。

不由得怀疑自己是不是完全理解错了。于是在watches中查找对应的数据


重新读了一下自己的程序,发现问题了……


func是【大段定语】指针啊!

不管定语有多长它都是个指针啊!!

没初始化地址啊!!!

野指针啊!!!!


由于隐式初始化的关系,倒也谈不上危险,不过无法运行是肯定的了。改进如下。


#include<cstdio>
using namespace std;

int (*(*pfunc)[5])(void*);
int a(void *pa){
    return 0;
}
int b(void *pb){
    return 1;
}
int c(void *pc){
    return 2;
}
int d(void *pd){
    return 3;
}
int e(void *pd){
    return 4;
}


int main()
{
    int (*func[5])(void*);
    pfunc=&func;

    func[0]=a;
    func[1]=b;
    func[2]=c;
    (*pfunc)[3]=d;
    (*pfunc)[4]=e;

    int *pn;
    int ans;
    int h=20;

    pn=&h;
    ans = (*(*pfunc)[3])((int *)pn);
    printf("%d",ans);

    return 0;
}


额外声明了一个数组,与指针相对应。

取这个数组的地址赋给指针。

再把数组内元素分别赋以函数地址,这里分别用直接法和间接法赋地址。

这样就不会出事故了。


总之是千万要注意野指针

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值