[英]Why doesn't reinterpret_cast convert 'unsigned char' to 'char'?
[英]reinterpret_cast unsigned char* as uint64_t* - is this UB?
假設我們采用了unsigned char
。
std::array<uint8_t, 100500> blob;
// ... fill array ...
(注意:它已經對齊,問題不是關於對齊。)然后我們把它作為uint64_t[]
並嘗試訪問它:
const auto ptr = reinterpret_cast<const uint64_t*>(blob.data());
std::cout << ptr[7] << std::endl;
轉向uint64_t
然后從中讀取對我來說看起來很可疑。
但UBsan, -Wstrict-aliasing
並沒有觸發它。 Google在FlatBuffers中使用此技術。 此外,Cap'n'Proto使用這個太 。
是不確定的行為?
您無法通過其他類型的glvalue訪問unsigned char
對象值。 但相反的是授權,您可以通過unsigned char
glvalue [basic.lval]訪問任何對象的值:
如果程序試圖通過以下類型之一以外的glvalue訪問對象的存儲值,則行為未定義:[...]
char
,unsigned char
或std::byte
類型。
因此,要符合100%標准,我們的想法是顛倒reinterpret_cast
:
uint64_t i;
std::memcpy(&i, blob.data() + 7*sizeof(uint64_t), sizeof(uint64_t));
std::cout << i << std::endl;
它將產生完全相同的組件 。
轉換本身定義良好( reinterpret_cast
永遠不會有UB),但如果在該地址中沒有構造uint64_t
對象,則表達式“ ptr[7]
”中的左值轉換的左值將是UB。
由於未顯示“ // ... fill array ...
”,因此可能在該地址中構造了一個uint64_t
對象(假設您所說的地址具有足夠的對齊):
const uint64_t* p = new (blob.data() + 7 * sizeof(uint64_t)) uint64_t();
如果在該地址中構造了uint64_t
對象,則所討論的代碼具有明確定義的行為。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.