[英]Is reintrepret_cast to char* well defined when the char array is modified?
從套接字接收預期消息時,請考慮以下示例:
struct myData {
uint8_t type;
int value;
}
myData readFromSocket(int socketFD) {
myData data{};
ssize_t bytes = recv(socketFD, reinterpret_cast<char*>(&data), sizeof(myData), 0);
if(bytes == sizeof(myData))
return data;
return myData{};
}
在這個例子中,我不清楚行為是否定義明確。
根據cppreference.com 上的reintrpret_cast,該行為定義良好,可以進行檢查,因為 char 的對齊方式不如 myData 的對齊方式嚴格,並且因為強制轉換專門針對 char 指針。 我不清楚檢查是專用於讀取還是包括對轉換指針的寫入。
5)根據說明:
任何對象指針類型 T1* 都可以轉換為另一個對象指針類型 cv T2*。 這完全等同於 static_cast<cv T2*>(static_cast<cv void*>(expression)) (這意味着如果 T2 的對齊要求不比 T1 嚴格,則指針的值不會改變並轉換結果指針回到其原始類型產生原始值)。 在任何情況下,只有在類型別名規則允許的情況下,結果指針才能安全地解除引用(見下文)
以及類型別名的第三點:
AliasedType 是 std::byte (C++17 起)、char 或 unsigned char:這允許檢查任何對象作為字節數組的對象表示。
我已經測試了與上述類似的代碼,沒有任何問題,但是由於這一切都歸結為編譯器做了哪些優化,我發現很難給出一個可能失敗的確切示例。
這篇文章提到了在另一個方向上的轉換,即從char*
到myData
會受到未定義行為的影響,並建議使用memcpy()
。 我的假設是,由於類型別名規則未涵蓋強制轉換,因此得出了這個結論。
然而,這個郵件線程懷疑memcpy()
,根據標准,是否應該提供保證(見下面的引用)並且沒有閱讀我傾向於同意的標准,因為它看起來對memcpy()
進行了相同的轉換至於recv()
。
在 C++ 社區中,當前的想法是 memcpy 允許輸入雙關語,但是 IIRC C++ 標准實際上甚至不清楚為什么會這樣,並且在其當前的編寫中可能實際上沒有辦法。
無論如何,如果有人對此有所了解並且可以提供一些幫助,我將不勝感激。 我對這個問題的興趣更多是學術性的,而不是實際的。 我已經用 c++17 標記了它,因為這是我的工作,歡迎對其他標准的見解。
C++ 標准在[basic.lval]/p8 中指定別名規則:
如果程序嘗試通過以下類型之一以外的泛左值訪問對象的存儲值,則行為未定義:
. . .
—char
、unsigned char
或std::byte
類型。
術語訪問在[defns.access] 中指定:
⟨執行時動作⟩ 讀取或修改對象的值
除此之外,沒有其他規則表明別名是單向工作的。
所以我們可以得出結論,別名是雙向的,代碼是可以的。
但是請注意,如果被覆蓋的對象包含const
成員,那么您應該在覆蓋后進行std::launder
,否則編譯器被允許假定const
成員永遠不會改變。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.