打印

如何理解函数指针的调用

[复制链接]
1579|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
entepino|  楼主 | 2012-10-11 17:33 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
如何理解函数指针的调用?
  这是函数在程序中的调用,如下:
XCan_SetHandler(&Can, XCAN_HANDLER_SEND,

(void *)SendHandler, (void *)&Can);

有四个参数,&CanXCAN_HANDLER_SENDSendHandler&Can;这个函数的定义是这样的,如下:
int XCan_SetHandler(XCan *InstancePtr, u32 HandlerType,


void *CallBackFunc, void *CallBackRef)
我就是没明白参数SendHandler是如何使用的?SendHandler本身是一个函数,其定义如下:
static
void SendHandler(void *CallBackRef)
{

/* The frame was sent successfully. Notify the task context */

xil_printf("SendHandler\r\n");

SendDone = XTRUE;
}

如果是函数指针作为参数的话,不应该这么写吗:(void *)SendHandler(void *)
即:XCan_SetHandler(&Can, XCAN_HANDLER_SEND,

(void *)SendHandler(void *), (void *)&Can);
有人知道吗,谢谢指点。

相关帖子

沙发
entepino|  楼主 | 2012-10-11 22:13 | 只看该作者
顶一下,难道没有人知道吗?

使用特权

评论回复
板凳
Tinnal| | 2012-10-12 11:03 | 只看该作者
本帖最后由 Tinnal 于 2012-10-12 11:04 编辑

你不应该把一个程序的问题,发在一个以讨论硬件为主的论坛,我想,如果你把这个问题发在csdn上,你等到回就的时间会短点。就你这个问题而言。
问题:
如果是函数指针作为参数的话,不应该这么写吗:(void *)SendHandler(void *)
答:
XCan_SetHandler(, ,(void *)SendHandler,); 是指把SendHandler的函数地址作为产生传递给XCan_SetHandler。
这里有(void *)是把SendHandler函数的类型扔掉,其实这是不好的。但也不是不行的。只要在用的时候再强制类型转换回来就行。

使用特权

评论回复
地板
Tinnal| | 2012-10-12 11:11 | 只看该作者
本帖最后由 Tinnal 于 2012-10-12 20:02 编辑

最好的写法是:
声明:
int XCan_SetHandler(XCan *InstancePtr, u32 HandlerType, void (*CallBackFunc)(void *), void *CallBackRef)
调用:
int XCan_SetHandler(..., ..., SendHandler, ...)

使用特权

评论回复
5
entepino|  楼主 | 2012-10-12 12:56 | 只看该作者
谢谢Tinnal的回复。

使用特权

评论回复
6
airwill| | 2012-10-12 19:05 | 只看该作者
函数指针的声明方法为:
  函数类型 (标志符 指针变量名) (形参列表);
  “函数类型”说明函数的返回类型,“(标志符 指针变量名 )”中的括号不能省,若省略整体则成为一个函数说明,说明了一个返回的数据类型是指针的函数,后面的“形参列表”表示指针变量指向的函数所带的参数列表。例如:
  int func(int x);             /* 声明一个函数 */
  int (*f) (int x);             /* 声明一个函数指针 */
  f=func;                        /* 将func函数的首地址赋给指针f */

使用特权

评论回复
7
Tinnal| | 2012-10-12 20:05 | 只看该作者
5# entepino 唉,晕死了。粗心大意,竟然给你写的代码是错的。请你留意,4楼的代码修正过的。

使用特权

评论回复
8
entepino|  楼主 | 2012-10-14 13:07 | 只看该作者
还是有点不太理解,是不是可以这么理解:
在调用此函数int XCan_SetHandler(XCan *InstancePtr, u32 HandlerType,void *CallBackFunc, void *CallBackRef)时,如果把结构体变量CAN1赋给形参void *CallBackFunc,此时应该这么写:XCan_SetHandler(&Can, XCAN_HANDLER_SEND,(void *)&CAN1, (void *)&Can);如果把int变量CAN2赋给形参void *CallBackFunc,此时就这么写了:XCan_SetHandler(&Can, XCAN_HANDLER_SEND,(void *)&CAN2, (void *)&Can);对吗?谢谢!

使用特权

评论回复
9
entepino|  楼主 | 2012-10-14 19:07 | 只看该作者
顶一下

使用特权

评论回复
10
Tinnal| | 2012-10-14 22:36 | 只看该作者
你对函数指针还是很不了解。
1. 你这种void *CallBackFunc的函数针写法,虽然能用,但已经不合常理。
2. 都说是函数指针了,指向的是函数,你怎么把它指向你的结构体变量CAN1和int变量CAN2呢?

给你几编**,你自己好好从基础学一学吧。
http://www.cppblog.com/andylei/archive/2010/02/04/107180.aspx
http://www.cnblogs.com/uniqueliu/archive/2011/07/27/2118619.html
http://blog.csdn.net/son_of_sky/article/details/546618

使用特权

评论回复
11
entepino|  楼主 | 2012-10-15 22:41 | 只看该作者
10# Tinnal
我觉得应该是可以的,形参的原型是空指针*CallBackFunc,只要在函数int XCan_SetHandler(XCan *InstancePtr, u32 HandlerType,void *CallBackFunc, void *CallBackRef)中,void *CallBackFunc是结构体变量的地址接受的,就可以这样写的,XCan_SetHandler(&Can, XCAN_HANDLER_SEND,(void *)&CAN1, (void *)&Can)。同样,如果在函数int XCan_SetHandler(XCan *InstancePtr, u32 HandlerType,void *CallBackFunc, void *CallBackRef)中,void *CallBackFunc是整形变量的地址接受的,应该也可以写成:XCan_SetHandler(&Can, XCAN_HANDLER_SEND,(void *)&CAN2, (void *)&Can),对不对啊,谢谢!

使用特权

评论回复
12
Tinnal| | 2012-10-16 00:41 | 只看该作者
原则上void*可以接受任何类型的的指针。因此,从语法上来说,你的这种型式的调用是可以的。但这是只原则。
你要搞清楚你这个XCan_SetHandler函数的用途。我所说的不合常理,是因为根据你这个函数名,我可以猜测这个函数是用来安装一个处理函数的,因为参数传进去的应该包含一个函数指针,而型参当中,只有CallBackFunc最合其意。因此,用它来传递其函数的结构体或整型指针不合理。

我没有你完整的程序,我的推论只是从你仅有的只个函数名的用途来判断。C语言的语法是很灵活的,为了增强程序的可读性,请尽量用具体的类型,少用void*。

再次强调,一切以你的实际程序为基础,这个函数作为是什么,每个参数接受什么,要从函数的内部实现来看,而非一个函数名可以定断的!

使用特权

评论回复
13
entepino|  楼主 | 2012-10-16 12:38 | 只看该作者
谢谢Tinnal回复,我明白了您的意思,也谢谢您的几篇**,给你散分,谢谢!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

211

主题

649

帖子

2

粉丝