考虑以下代码:
void MemMove8(void* dst, void* src)
{
char tmp[8];
memcpy(tmp, src, 8);
memcpy(dst, tmp, 8);
}
使用 /O2 选项编译的 MSVC(16.7.1 版)x86 架构生成该函数的以下汇编代码:
; _dst$ = ecx
; _src$ = edx
mov eax, DWORD PTR [edx]
mov DWORD PTR [ecx], eax
mov eax, DWORD PTR [edx+4]
mov DWORD PTR [ecx+4], eax
但是如果输入和输出缓冲区重叠,这种方法在某些情况下是无效的。
生成的代码对我来说似乎有问题;或者说这是一种有效的转换,而我可能忽略了什么?
src
中的内容复制到临时缓冲区tmp
中。然后再从tmp
复制到dst
中。临时缓冲区不会与src
或dst
重叠。 - Alex#include <cstring>
和using std::memcpy;
还是使用全局命名空间中的::memcpy
(来自<string.h>
)?我无法访问针对 x86 目标的 MSVC 16.7.1。 - Eljaystd::memmove
可以解决这个问题?(我希望 godbolt 有 MSVC 16.7.1 x86。)在我的平台上,::memcpy
和std::memcpy
的定义是不同的(但那不是 MSVC 16.7.1)。 - Eljay::memcpy
函数导入std命名空间。因此,memcpy
和std::memcpy
实际上是相同的。MemMove8
函数之所以存在,是因为MSVC不会“内联”memmove(dst, src, 8)
(调用库函数而不是生成一些mov
指令),但它会“内联”std::memcpy(dst, src, 8)
。这只是一种性能优化。 - Alex