memmove 并没有真正移动内存,不是吗?它只是将内存从一个区域复制到另一个区域,并允许这两个区域重叠。我问这个问题是因为我只想知道为什么这个 fnc 以非常误导的方式被调用。
因为我知道当某物从一个地方移动到另一个地方时,“东西”是在这个操作之后在另一个地方而不是在第一个地方。而使用 memmove 则不能那样工作。我对吗?
7 回答
你是对的,它复制了它。但是 和 之间是有区别的memmove
,memcpy
因为memmove
可以正确处理缓冲区重叠的情况,所以推荐在这些情况下使用。
但是,由于执行了额外的检查memmove
,当缓冲区很小并且肯定不重叠时,memcpy
效果会更好。
memcpy()
和之间的区别在于memmove()
始终memmove()
可以安全使用,而不管源和目标之间的别名如何。就好像memmove()
先将数据复制到临时缓冲区,然后再复制到目标。 memcpy()
不提供任何别名保证。它可能会按预期工作,但可能不会。如果您知道缓冲区不能重叠,memcpy()
那很好,并且可以在任何给定的库中使用允许它比memmove()
. 在另一个库memcpy()
中实际上可能只是memmove()
.
如果您知道 src 和 dst 不能是别名,那么使用memcpy()
. 如果您不知道哪一种适用于您,请使用memmove()
.
该函数如此命名是因为如果被复制的内存区域碰巧重叠,则它不再是副本,因为原始缓冲区不再不变。因此,原始缓冲区应被视为不可用。由于您使用的是 memmove 而不是 memcpy,因此很可能是这种情况。因此命名是有意义的:从语义上讲,您是在移动数据而不是复制它。
Memmove将数据从源 复制到目标。它与memcpy的不同之处在于它保证在重叠的内存区域上工作。
是的,memmove
确实memcpy
具有处理重叠块的能力。假设您有一个数组,并且您想在开头插入一些新项目(或删除一些项目),那么您所做的就是来回“移动”(现有或剩余的)项目 - 我猜,并且在这种情况下,这个名字是有道理的。
是的,memmove
是副本的另一个变体。它不会“移动”内存,因为原始字节不再是操作之前的样子。专门处理内存重叠的情况。
这如何完成取决于您的架构,但我已经看到它以两种不同的方式完成:
- 使用具有两个 memcpy 类型操作的临时缓冲区;或者
- 从第一个字节向前复制或从最后一个字节向后复制,具体取决于重叠类型(如果有)。
要回答您关于memmove()
' 名称的问题:我认为该名称旨在反映对将数组中的元素范围移动到数组中的另一个范围的支持(例如,在数组的开头或内部为新元素腾出空间)。
正如其他答案所提到的,memcpy()
可以使用不可用的优化技术,memmove()
因为memcpy()
不支持重叠的内存区域,而支持memmove()
。
您可能要考虑的一件事是仍然使用memmove()
而不是memcpy()
默认使用,除非您正在处理复制性能至关重要的应用程序。memcpy()
可以提供更好的性能(主要是因为它可以更有效地内联,我认为),但请记住以下关于Linux 内核中实现的引用memcpy()
来自关于应用程序不正确使用 C 库的讨论memcpy()
:
在内核中,我们使用的优化的 x86 memcpy 实际上是一个 memmove(),因为虽然性能确实很重要,但可重复性和避免意外也很重要(严格来说,我们有两个:“rep movs”版本,用于应该是快速的,并且是开放编码的副本版本。“rep movs”版本仅转发并且不处理重叠区域)。