![](/img/trans.png)
[英]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.