在 C++ 中从任意内存地址读取 UInt32 值的最有效方法是什么? (假设 Windows x86 或 Windows x64 架构。)
例如,考虑有一个字节指针指向内存中某处的 block ,该 block 包含整数、字符串数据等的组合,所有这些都混合在一起。以下示例显示循环读取此 block 中的各个字段。
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 字节对齐的地址,读取 UInt32 应该是一次内存读取。如果 pPtr
包含非对齐地址,则可能需要多个内存周期,这会减慢代码速度。有没有更快的方法从非对齐地址读取值?
最佳答案
我建议将 memcpy 放入循环中的 UInt32 类型的临时文件中。
这利用了一个事实,即在启用优化的情况下构建时,编译器将内联一个四字节的 memcpy,并且还有一些其他好处:
- 如果您使用的平台对齐很重要(hpux、solaris sparc 等),您的代码就不会陷入困境。
- 在对齐很重要的平台上,可能值得对对齐进行地址检查,然后进行常规对齐加载或一组 4 字节加载和位或。您的编译器的 memcpy 很可能会以最佳方式执行此操作。
- 如果您使用的平台允许未对齐访问且不会影响性能(x86、x64、powerpc 等),那么可以肯定,这样的 memcpy 将是最便宜的方式进行此访问。
- 如果您的内存最初是指向其他数据结构的指针,则您的代码可能由于别名问题而未定义,因为您正在转换为另一种类型并取消引用该转换。由于与别名相关的优化问题导致的运行时问题很难追踪!假设您可以弄清楚它们,修复已建立的代码也可能非常困难,您可能不得不使用晦涩的编译选项,如 -fno-strict-aliasing 或 -qansialias,这会显着限制编译器的优化能力。
关于c++ - 从任何内存地址读取 UInt32 的最有效方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8998274/