[英]What is the difference between these two C function calls?
我以兩種方式調用以下庫函數:
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 *)
,它看起來像是一個函數指針給我?
指向void
的指針是“通用”指針類型。 void *
可以在沒有顯式強制轉換的情況下轉換為任何其他指針類型。 你不能取消引用void *
或用它做指針算術; 您必須首先將其轉換為指向完整數據類型的指針。 看到這個答案 。
因此參數pMsg
不能直接與lsMsg *兼容,那么第二次調用是在函數調用中使用它的一種可能方式[我沒有測試過它]。
順便說一句,只要pMsg
類型是lsMsg *
,第一個就足夠了。
編輯:
第二個足夠,因為它涵蓋了第一個。
第二個版本是正確的。
第一個調用看起來像是試圖躲避不兼容類型的警告。 如果pMsg
與lsMsg *
不兼容, lsMsg *
可以通過在兩者之間轉換為void*
來lsMsg *
編譯器警告。
你不應該這樣做,因為它幾乎肯定會隱藏你的程序中的錯誤! 兩種指針類型完全不兼容,在這種情況下程序可能會在訪問指針時立即崩潰和燒毀。 或者它們在理論上是兼容的,但是編譯器實現了類型別名,然后(void*)
強制轉換會隱藏違反“嚴格別名規則”的行為。 在任何一種情況下,您都有未定義的行為和嚴重的錯誤。
我認為沒有理由第一種方式將指針類型轉換兩次。 只需使用第二種方式即可。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.