memmove 和 memcpy 有什么区别?
memmove
和 memcpy
之间有什么区别? 您通常使用哪一种以及如何使用?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
memmove
和 memcpy
之间有什么区别? 您通常使用哪一种以及如何使用?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(10)
使用memcpy,目标根本不能与源重叠。 使用
memmove
就可以了。 这意味着memmove
可能比memcpy
慢一点,因为它无法做出相同的假设。例如,memcpy 可能总是从低位到高位复制地址。 如果目标在源之后重叠,则意味着某些地址将在复制之前被覆盖。 在这种情况下,memmove 会检测到这一点并沿另一个方向复制 - 从高到低。 然而,检查这一点并切换到另一种(可能效率较低)算法需要时间。
With
memcpy
, the destination cannot overlap the source at all. Withmemmove
it can. This means thatmemmove
might be very slightly slower thanmemcpy
, as it cannot make the same assumptions.For example,
memcpy
might always copy addresses from low to high. If the destination overlaps after the source, this means some addresses will be overwritten before copied.memmove
would detect this and copy in the other direction - from high to low - in this case. However, checking this and switching to another (possibly less efficient) algorithm takes time.memmove
可以处理重叠内存,memcpy
不能。考虑
显然源和目的地现在重叠,我们正在覆盖
“-bar”与“bar”。 如果源和目标重叠,
memcpy
可能会导致未定义的行为,因此在这种情况下我们需要memmove
。memmove
can handle overlapping memory,memcpy
can't.Consider
Obviously the source and destination now overlap, we're overwriting
"-bar" with "bar".
memcpy
can cause undefined behavior if the source and destination overlap, so in this case we needmemmove
.假设您必须同时实现两者,那么实现可能如下所示:
这应该很好地解释了差异。
memmove
总是以这样的方式进行复制,即使src
和dst
重叠,它仍然是安全的,而memcpy
只是不在乎,正如文档所说,当使用memcpy
时,两个内存区域不得重叠。例如,如果memcpy“从前到后”复制并且内存块对齐,因为
将
src
的第一个字节复制到dst
已经破坏了内容复制这些之前src
的最后一个字节。 只有“从后到前”复制才能得到正确的结果。现在交换
src
和dst
:在这种情况下,只有“从前到后”复制才是安全的,因为“从后到前”复制会破坏
src
当复制第一个字节时已经靠近它的前面了。您可能已经注意到,上面的
memmove
实现甚至不测试它们是否确实重叠,它只是检查它们的相对位置,但仅此一点就可以使副本安全。 由于memcpy
通常使用最快的方式在任何系统上复制内存,因此memmove
通常实现为:有时,如果
memcpy
总是复制 "从前到后”或“从后到前”,memmove
也可以在其中一种重叠情况下使用memcpy
,但memcpy
甚至可以复制到根据数据对齐方式和/或要复制的数据量而采用不同的方式,因此即使您测试了memcpy在系统上的复制方式,您也不能依赖该测试结果始终正确。当您决定打电话给哪一个时,这对您意味着什么?
除非您确定
src
和dst
不重叠,否则调用memmove
因为它总是会产生正确的结果,并且通常,您需要的复印情况尽可能快。如果您确定
src
和dst
不重叠,请调用memcpy
,因为调用哪一个并不重要对于结果,在这种情况下两者都可以正常工作,但是memmove
永远不会比memcpy
更快,如果你不幸运,它甚至可能会更慢,所以你只能win 调用memcpy
。Assuming you would have to implement both, the implementation could look like that:
And this should pretty well explain the difference.
memmove
always copies in such a way, that it is still safe ifsrc
anddst
overlap, whereasmemcpy
just doesn't care as the documentation says when usingmemcpy
, the two memory areas must not overlap.E.g. if
memcpy
copies "front to back" and the memory blocks are aligned as thiscopying the first byte of
src
todst
already destroys the content of the last bytes ofsrc
before these have been copied. Only copying "back to front" will lead to correct results.Now swap
src
anddst
:In that case it's only safe to copy "front to back" as copying "back to front" would destroy
src
near its front already when copying the first byte.You may have noticed that the
memmove
implementation above doesn't even test if they actually do overlap, it just checks their relative positions, but that alone will make the copy safe. Asmemcpy
usually uses the fastest way possible to copy memory on any system,memmove
is usually rather implemented as:Sometimes, if
memcpy
always copies "front to back" or "back to front",memmove
may also usememcpy
in one of the overlapping cases butmemcpy
may even copy in a different way depending on how the data is aligned and/or how much data is to be copied, so even if you tested howmemcpy
copies on your system, you cannot rely on that test result to be always correct.What does that mean for you when deciding which one to call?
Unless you know for sure that
src
anddst
don't overlap, callmemmove
as it will always lead to correct results and is usually as fast as that is possible for the copy case you require.If you know for sure that
src
anddst
don't overlap, callmemcpy
as it won't matter which one you call for the result, both will work correctly in that case, butmemmove
will never be faster thanmemcpy
and if you are unlucky, it may even be slower, so you can only win callingmemcpy
.来自 memcpy 手册页。
From the memcpy man page.
memmove()
和memcpy()
之间的主要区别在于memmove()
中有一个 缓冲区 - 临时内存- 使用,因此不存在重叠的风险。 另一方面,memcpy()
直接将数据从源指向的位置复制到目标指向的位置。 (http://www.cplusplus.com/reference/cstring/memcpy/)考虑以下示例:
如您所料,这将打印出来:
但在本示例中,结果将不同:
输出:
这是因为“memcpy()”执行以下操作:
The main difference between
memmove()
andmemcpy()
is that inmemmove()
a buffer - temporary memory - is used, so there is no risk of overlapping. On the other hand,memcpy()
directly copies the data from the location that is pointed by the source to the location pointed by the destination. (http://www.cplusplus.com/reference/cstring/memcpy/)Consider the following examples:
As you expected, this will print out:
But in this example, the results will not be the same:
Output:
It is because "memcpy()" does the following:
一个 (
memmove
) 处理重叠的目标,另一个 (memcpy
) 则不处理。One (
memmove
) handles overlapping destinations the other (memcpy
) doesn't.ISO/IEC:9899 标准对此进行了很好的描述。
并且
我通常根据问题使用哪一个,取决于我需要什么功能。
在纯文本中,
memcpy()
不允许s1
和s2
重叠,而memmove()
则允许。simply from the ISO/IEC:9899 standard it is well described.
And
Which one I usually use acording to the question, depends on what functionallity I need.
In plain text
memcpy()
doesn't allows1
ands2
to overlap, whilememmove()
does.有两种明显的方法可以实现 mempcpy(void *dest, const void *src, size_t n)(忽略返回值):
在第一个实现中,复制从低地址到高地址进行,而在第二个实现中,复制从高地址到低地址进行。 如果要复制的范围重叠(例如滚动帧缓冲区时的情况),则只有一个操作方向是正确的,而另一个操作方向将覆盖随后读取的位置。
最简单的
memmove()
实现将测试dest (以某种依赖于平台的方式),并执行
memcpy() 的适当方向
。用户代码当然不能这样做,因为即使在将 src 和 dst 转换为某种具体的指针类型之后,它们(通常)也不会指向同一个对象所以不能比较。 但标准库可以拥有足够的平台知识来执行此类比较,而不会导致未定义的行为。
请注意,在现实生活中,实现往往要复杂得多,以便从较大的传输(当对齐允许时)和/或良好的数据缓存利用率中获得最大性能。 上面的代码只是为了尽可能简单地阐明这一点。
There are two obvious ways to implement
mempcpy(void *dest, const void *src, size_t n)
(ignoring the return value):In the first implementation, the copy proceeds from low to high addresses, and in the second, from high to low. If the range to be copied overlaps (as is the case when scrolling a framebuffer, for example), then only one direction of operation is correct, and the other will overwrite locations that will subsequently be read from.
A
memmove()
implementation, at its simplest, will testdest<src
(in some platform-dependent way), and execute the appropriate direction ofmemcpy()
.User code can't do that of course, because even after casting
src
anddst
to some concrete pointer type, they don't (in general) point into the same object and so can't be compared. But the standard library can have enough platform knowledge to perform such a comparison without causing Undefined Behaviour.Note that in real life, implementations tend to be significantly more complex, to gain the maximum performance from larger transfers (when alignment permits) and/or good data cache utilisation. The code above is just to make the point as simply as possible.
在Windows操作系统中,ntdll.dll还导出名为memcpy和memmove的函数,它们实际上是同一个函数(以及RtlCopyMemory和RtlMoveMemory)功能)。 此屏幕截图来自
ntdll.dll
的 x64dbg 符号选项卡In Windows operating system,
ntdll.dll
also exports functions namedmemcpy
andmemmove
, and they are actually the same function (along with RtlCopyMemory and RtlMoveMemory functions). This screenshot is from x64dbg symbols tab forntdll.dll
memmove 可以处理重叠的源区域和目标区域,而 memcpy 则不能。 两者之中,memcpy 的效率要高得多。 因此,如果可以的话,最好使用 memcpy 。
参考:https://www.youtube.com/watch?v=Yr1YnOVG-4g< /a> Jerry Cain 博士,(斯坦福介绍系统讲座 - 7)时间:36:00
memmove can deal with overlapping source and destination regions, while memcpy cannot. Among the two, memcpy is much more efficient. So, better to USE memcpy it if you can.
Reference: https://www.youtube.com/watch?v=Yr1YnOVG-4g Dr. Jerry Cain, (Stanford Intro Systems Lecture - 7) Time: 36:00