我在尝试遍历运行时已知字节长度的字节数组时遇到了这个问题。https://godbolt.org/z/-vgEk_
#include <cstdint>
void f()
{
uint8_t* array = new uint8_t[4*10];
// cannot convert 'unsigned char*' to 'unsigned int*' in initialization
uint32_t* fourByteIterator1 = array;
// invalid static_cast from 'unsigned char*' to 'unsigned int*'
uint32_t* fourByteIterator2 = static_cast<uint32_t*>(array);
// no problems
uint32_t* fourByteIterator3 = (uint32_t*)array;
// no problems
void* intermediate = static_cast<void*>(array);
uint32_t* fourByteIterator4 = static_cast<uint32_t*>(p);
// no problems
uint32_t* fourByteIterator5 = reinterpret_cast<uint32_t*>(array);
}
为什么static_cast
第二次转换失败?然后,如果直接转换为using 时,从转换void*
为to 无效,为什么有效?是否通过与直接重新解释转换相同的方式将指针类型静态转换为两次?uint32_t*
uint32_t*
static_cast
void*
uint32_t* fourByteIterator1 = (whatever_cast)array;
fourByteIterator1
无论您如何设法使演员正常工作,访问都是未定义的行为。访问从new uint8_t[4*10];
作为类型对象获得的内存uint32_t
违反了严格的别名规则。
至于为什么某些强制转换方法起作用而其他无效的原因……这就是标准所说的。这些规则就像是在保护您避免犯错误。除了with之外,您无法在其他对象之间直接进行转换,这reinterprect_cast
很好地表明您可能不应该这样做。
强制转换通过void*
起作用,因为可以将任何指针类型都强制转换为对象,void *
并且如果您强制转换为原始指针类型,则可以保证将原始指针取回。这就是为什么比void *
其他指针类型更“允许” 与“来自”的转换。但这不是你在做什么。您没有回退到原始指针类型。
通过void *两次静态转换指针类型是否与直接重新解释转换相同?
是。
结论:不要那样做。这是未定义的行为。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句