c - memmove 和 memcpy 有什么区别?

c - memmove 和 memcpy 有什么区别?

假设您必须同时实现两者,则实现可能如下所示:

void memmove ( void * dst, const void * src, size_t count ) {

if ((uintptr_t)src < (uintptr_t)dst) {

// Copy from back to front

} else if ((uintptr_t)dst < (uintptr_t)src) {

// Copy from front to back

}

}

void memcpy ( void * dst, const void * src, size_t count ) {

if ((uintptr_t)src != (uintptr_t)dst) {

// Copy in any way you want

}

}

这应该很好地解释了差异。memmove总是以这样的方式复制,如果src和dst重叠它仍然是安全的,而memcpy正如文档所说的那样,使用时并不关心memcpy,两个内存区域不能重叠。

例如,如果memcpy复制“从前到后”并且内存块是这样对齐的

[---- src ----]

[---- dst ---]

复制srcto的第一个字节dst已经破坏了src复制之前最后一个字节的内容。只有“从后到前”复制才能得到正确的结果。

现在交换src和dst:

[---- dst ----]

[---- src ---]

在这种情况下,复制“从前到后”是安全的,因为src在复制第一个字节时,复制“从后到前”会破坏它的前面。

您可能已经注意到,memmove上面的实现甚至没有测试它们是否真的重叠,它只是检查它们的相对位置,但仅此一点就可以使副本安全。由于memcpy通常使用最快的方式在任何系统上复制内存,memmove通常是这样实现的:

void memmove ( void * dst, const void * src, size_t count ) {

if ((uintptr_t)src < (uintptr_t)dst

&& (uintptr_t)src + count > (uintptr_t)dst

) {

// Copy from back to front

} else if ((uintptr_t)dst < (uintptr_t)src

&& (uintptr_t)dst + count > (uintptr_t)src

) {

// Copy from front to back

} else {

// They don't overlap for sure

memcpy(dst, src, count);

}

}

有时,如果memcpy总是“从前到后”或“从后到前”复制,memmove也可以memcpy在其中一种重叠情况下使用,但memcpy甚至可以根据数据的对齐方式和/或数据量以不同的方式复制复制,因此即使您测试了memcpy系统上的复制方式,您也不能依赖该测试结果始终正确。

在决定打电话给哪一个时,这对您意味着什么?

除非您确定src并且dst不重叠,否则调用memmove,因为它总是会导致正确的结果,并且对于您需要的复制案例通常尽可能快。

如果您确定src并且dst不重叠,请调用memcpy,因为无论您调用哪个结果都无关紧要,在这种情况下两者都可以正常工作,但memmove永远不会比你更快memcpy,如果你不走运,它甚至可能慢一点,所以你只能赢得 call memcpy。

相关推荐

笔记本清灰换硅脂需要多少钱?
体育365投注官网

笔记本清灰换硅脂需要多少钱?

📅 07-03 👁️ 8267
服务器性能如何优化?(建议收藏)
bet28365365备用

服务器性能如何优化?(建议收藏)

📅 08-10 👁️ 7858