c – 从任何内存地址读取UInt32的最有效方法?
作者:互联网
从C中的任意内存地址读取UInt32值的最有效方法是什么? (假设Windows x86或Windows x64架构.)
例如,考虑使用一个指向内存中某处的字节指针来阻止包含整数,字符串数据等的组合,这些组合都混合在一起.以下示例显示了在循环中从此块读取各个字段.
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字节加载和位ors之一.您的编译器的memcpy很可能会以最佳方式执行此操作.
>如果您所在的平台上允许未对齐访问并且不会影响性能(x86,x64,powerpc,…),那么您几乎可以保证这样的memcpy将是最便宜的方式这种访问.
>如果您的内存最初是指向其他数据结构的指针,则由于别名问题,您的代码可能未定义,因为您正在转换为其他类型并取消引用该转换.由于别名相关的优化问题导致的运行时问题非常难以追查!假设您可以解决它们,在已建立的代码中修复也可能非常困难,您可能必须使用模糊的编译选项,如-fno-strict-aliasing或-qansialias,这可能会显着限制编译器的优化能力.
标签:c,x86,windows,memory-alignment,64-bit 来源: https://codeday.me/bug/20190826/1731286.html