簡體   English   中英

修改 char 數組時,reintrepret_cast to char* 是否定義良好?

[英]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 中指定別名規則:

如果程序嘗試通過以下類型之一以外的泛左值訪問對象的存儲值,則行為未定義:
. . .
charunsigned charstd​::​byte類型。

術語訪問[defns.access] 中指定:

⟨執行時動作⟩ 讀取或修改對象的值

除此之外,沒有其他規則表明別名是單向工作的。

所以我們可以得出結論,別名是雙向的,代碼是可以的。

但是請注意,如果被覆蓋的對象包含const成員,那么您應該在覆蓋后進行std::launder ,否則編譯器被允許假定const成員永遠不會改變。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM