从C ++中的任意内存地址读取UInt32值最有效的方法是什么? (假设Windows x86或Windows x64架构)
例如,考虑有一个指向内存某处的字节指针,该指针包含ints,string数据等的组合,全部混合在一起。 以下示例显示了从循环中读取该块中的各个字段。
typedef unsigned char* BytePtr; typedef unsigned int UInt32; ... BytePtr pCurrent = ...; while ( *pCurrent != 0 ) { ... if ( *pCurrent == ... ) { UInt32 nValue = *( (UInt32*) ( pCurrent + 1 ) ); // line A ... } pCurrent += ...; }
如果在A
行, pPtr
碰巧包含一个4字节alignment的地址,读取UInt32应该是一次读取内存。 如果pPtr
包含一个不alignment的地址,我需要多于一个的内存循环,这会减慢代码的速度。 有没有更快的方式来读取非alignment地址的值?
我建议memcpy到您的循环内的类型的UInt32的临时。
这利用了一个事实,即在启用优化的情况下,编译器会将四个字节的memcpy内联,并具有其他一些优点:
你的代码是未定义的行为。
几乎所有唯一的“正确的”解决方案是只读取类型T
东西,如果它是类型T
,如下所示:
uint32_t n; char * p = point_me_to_random_memory(); std::copy(p, p + 4, reinterpret_cast<char*>(&n)); std::cout << "The value is: " << n << std::endl;
在这个例子中,你想要读取一个整数,唯一的办法是有一个整数。 如果您希望它包含某个二进制表示,则需要将该数据复制到变量开头的地址。
让编译器做优化!
UInt32 ReadU32(unsigned char *ptr) { return static_cast<UInt32>(ptr[0]) | (static_cast<UInt32>(ptr[1])<<8) | (static_cast<UInt32>(ptr[2])<<16) | (static_cast<UInt32>(ptr[3])<<24); }