有人可以帮助我理解如何在C中实现memmove。我只有一个特殊条件吗?
if((src<dst)&&((src+sz) > dst))
copy from the back
它还取决于堆栈的增长方式吗?
答案 0 :(得分:29)
在数学上,你不必担心它们是否重叠。如果src
小于dst
,请从最后复制。如果src
大于dst
,则只需从头开始复制。
如果src
和dst
相等,请立即退出。
那是因为你的案件是以下之一:
1) <-----s-----> start at end of s
<-----d----->
2) <-----s-----> start at end of s
<-----d----->
3) <-----s-----> no action
<-----d----->
4) <-----s-----> start at beginning of s
<-----d----->
5) <-----s-----> start at beginning of s
<-----d----->
即使没有重叠,这仍然可以正常工作,并简化您的条件。
如果您有一种更有效的方式来复制前进而不是后退,那么,是的,您应该检查重叠以确保您使用更有效的方法(如果可能)。换句话说,更改上面的选项1以从头开始复制。
答案 1 :(得分:5)
memmove转换为memcpy。 memcpy显然在大多数系统上都得到了极大的优化(我使用的其中一个系统使用了本书中几乎所有技巧,从展开的循环到支持最大吞吐量的SSE操作)。
如果两个内存区域重叠,则为了所有意图和目的,将要复制的区域移动到临时缓冲区中,并将临时缓冲区(最有可能是memcpy)复制回原始缓冲区之上。你不能从一开始就工作,或者从后面开始工作,重叠区域,因为你总是会在这个过程中至少有一些数据被破坏。
话虽如此,自从我查看libc代码已经有很长一段时间了,因此可能会对memmove和重叠区域进行优化,而我还没有想到。
memmove根本不依赖于堆栈的增长方式 - 它只是将一个内存区域复制到另一个位置 - 就像memcpy一样,除了它处理重叠区域而memcpy没有。编辑:实际上,再考虑一下......如果你从正确的“来源”(可以这么说)出发,可以从后面工作,这取决于移动本身(例如,来源&lt; dest或不?)。你可以阅读newlib的实现here,而且评论也相当好。
答案 2 :(得分:1)
取决于编译器。好的编译器将根据目标处理器指令集和总线宽度使用良好的优化。