c++ - 从任何内存地址读取 UInt32 的最有效方法?

标签 c++ windows x86 64-bit memory-alignment

在 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/

相关文章:

Linux 上的 php/mysql : development on Win, 部署

windows - CMD/Powershell : Commands not working with cURL. Cygwin 工作

c++ - 使用 Windows API 获取文件关联

c++ - 当前的 x86 架构是否支持非临时加载(来自 "normal"内存)?

assembly - INT %ebx 出了什么问题?

c++ - 尝试构建 Skia 时缺少头文件

python - 来回 unix 域套接字锁

C++ - 清理整数输入

c++ - 如何在 linux 上使用 Qt 或任何其他 cpp 框架播放 wma 音频文件?

assembly - 通过寄存器重命名器对寄存器进行微架构清零 : performance versus a mov?