我以两种方式调用以下库函数:
unsigned int
LsSendToQ(unsigned int p4Node, const char queueName[4], lsMsg *pMsg,
unsigned int prio) {
}
第一种方式:
LsSendToQ((unsigned int)0, (const char *)Q_NAME, (lsMsg *)(void *)pMsg, 0)
和第二种方式:
LsSendToQ((unsigned int)0, (const char *)Q_NAME, (lsMsg *)pMsg, 0)
两个调用编译都很好,但哪一个是正确的方法?为什么(void *)
在第一次调用中使用,它看起来像是指向我的函数指针?
答案 0 :(得分:3)
指向void
的指针是“通用”指针类型。可以将void *
转换为任何其他指针类型,而无需显式转换。你不能取消引用void *
或用它做指针算术;您必须首先将其转换为指向完整数据类型的指针。请参阅此answer。
因此参数pMsg
不能直接与lsMsg *兼容,那么第二次调用是一种在函数调用中使用它的可能方法[我没有测试过它]。
顺便说一句,只要pMsg
的类型为lsMsg *
,第一个就足够了。
编辑:
第二个足以覆盖第一个。
答案 1 :(得分:3)
第二个版本是正确的。
第一个电话看起来像是试图躲避不兼容类型的警告。如果pMsg
与lsMsg *
不兼容,您可以通过在其间转换为void*
来终止编译器警告。
你不应该这样做,因为它几乎肯定会隐藏你程序中的错误!两种指针类型完全不兼容,在这种情况下程序可能会立即崩溃。访问指针时刻录。或者它们在理论上是兼容的,但是编译器实现了类型别名,然后(void*)
强制转换会隐藏违反严格别名规则的行为#34;在任何一种情况下,您都有未定义的行为和严重的错误。
答案 2 :(得分:2)
我认为没有理由第一种方式将指针类型转换两次。只需使用第二种方式即可。