memmove和memcpy有什么区别?

memmovememcpy什么区别? 你通常使用哪一个?

使用memcpy ,目标不能与源重叠。 随着移动它可以。 这意味着memmove可能会比memcpy慢一点,因为它不能做出相同的假设。

例如, memcpy可能总是将地址从低到高复制。 如果目标在源之后重叠,这意味着某些地址在复制之前将被覆盖。 memmove会检测到这一点,并在另一个方向复制 – 在这种情况下,从高到低。 但是,检查这个并切换到另一个(可能效率较低)的algorithm需要时间。

memmove可以处理重叠的内存, memcpy不能。

考虑

 char[] str = "foo-bar"; memcpy(&str[3],&str[4],4); //might blow up 

显然源和目的地重叠,我们用“bar”覆盖“-bar”。 如果源和目标重叠,则使用memcpy是未定义的行为,所以在这种情况下,我们需要memmove

 memmove(&str[3],&str[4],4); //fine 

从memcpy手册页。

memcpy()函数从存储区src复制n个字节到存储区dest。 内存区域不应该重叠。 如果内存区域重叠,请使用memmove (3)。

一个处理重叠的目的地,另一个不处理。

memmove()memcpy()之间的主要区别是在memmove()缓冲区 – 临时内存 – 所以没有重叠的风险。 另一方面, memcpy()直接将数据从指向的位置复制到目标指向的位置。 ( http://www.cplusplus.com/reference/cstring/memcpy/

考虑下面的例子:

  1.  #include <stdio.h> #include <string.h> int main (void) { char string [] = "stackoverflow"; char *first, *second; first = string; second = string; puts(string); memcpy(first+5, first, 5); puts(first); memmove(second+5, second, 5); puts(second); return 0; } 

    如你所料,这将打印出来:

     stackoverflow stackstacklow stackstacklow 
  2. 但在这个例子中,结果将不一样:

     #include <stdio.h> #include <string.h> int main (void) { char string [] = "stackoverflow"; char *third, *fourth; third = string; fourth = string; puts(string); memcpy(third+5, third, 7); puts(third); memmove(fourth+5, fourth, 7); puts(fourth); return 0; } 

    输出:

     stackoverflow stackstackovw stackstackstw 

这是因为“memcpy()”执行以下操作:

 1. stackoverflow 2. stacksverflow 3. stacksterflow 4. stackstarflow 5. stackstacflow 6. stackstacklow 7. stackstacksow 8. stackstackstw 

简单地从ISO / IEC:9899标准就可以很好地描述。

7.21.2.1 memcpy函数

[…]

2 memcpy函数将s2指向的对象中的n个字符复制到s1指向的对象中。 如果在重叠的对象之间进行复制,则行为是不确定的。

7.21.2.2移动function

[…]

2 memmove函数将s2指向的对象中的n个字符复制到s1指向的对象中。 复制的过程与从s2指向的对象中的n个字符首先复制到n个字符的临时数组中,这些字符不与 s1和s2指向的对象重叠 ,然后将临时数组中的n个字符复制到s1指向的对象。

我通常根据问题select哪一个取决于我需要的function。

在纯文本中, memcpy()不允许s1s2重叠,而memmove()却是这样。

我试着运行上面的代码:主要原因我想知道memcpymemmove的区别。

 #include <stdio.h> #include <string.h> int main (void) { char string [] = "stackoverflow"; char *third, *fourth; third = string; fourth = string; puts(string); memcpy(third+5, third, 7); puts(third); memmove(fourth+5, fourth, 7); puts(fourth); return 0; } 

给出下面的输出

 stackoverflow stackstackovw stackstackstw 

现在我用memcpyreplace了memmove ,并得到了相同的输出

 #include <stdio.h> #include <string.h> int main (void) { char string [] = "stackoverflow"; char *first, *second; first = string; second = string; puts(string); memcpy(first+5, first,7); puts(first); memcpy(second+5, second, 7); puts(second); return 0; } 

输出:

 stackoverflow stackstackovw stackstackstw 

char string [] =“stackoverflow”;

 char *first, *second; first = string; second = string; puts(string); 

o / p – stackoverflow

 memcpy(first+5, first,7); puts(first); 

这里有7个由第二个指向的字符,即“stackov”粘贴在+5位置

o / p – stackstackovw

 memcpy(second+5, second, 7); puts(second); 

这里inputstring是“stackstackovw”,第二个字符(即“stackst”)被复制到一个缓冲区,然后粘贴到+5

o / p – stackstackstw

0 —– + 5
堆栈栈

有两种明显的方法来实现mempcpy(void *dest, const void *src, size_t n) (忽略返回值):

  1.  for (char *p=src, *q=dest; n-->0; ++p, ++q) *q=*p; 
  2.  char *p=src, *q=dest; while (n-->0) q[n]=p[n]; 

在第一个实现中,拷贝从低地址到高地址,而在第二个地址从高到低。 如果要复制的范围重叠(例如,滚动帧缓冲区的情况),则只有一个操作方向是正确的,另一个将覆盖随后将读取的位置。

一个简单的memmove()实现将testingdest<src (以某种依赖于平台的方式),并执行memcpy()的相应方向。

用户代码当然不能这样做,因为即使在将srcdst为某个具体的指针types之后,它们也不会(通常)指向同一个对象,因此无法进行比较。 但是标准库可以有足够的平台知识来执行这样的比较,而不会导致未定义的行为。


请注意,在现实生活中,实现往往要复杂得多,以便从较大的传输(在alignment允许时)和/或良好的数据高速caching利用率中获得最大的性能。 上面的代码只是为了尽可能简单地说明问题。

memmove可以处理重叠的源和目标区域,而memcpy不能。 其中memcpy更有效率。 所以,如果可以的话,最好使用memcpy。

参考: https : //www.youtube.com/watch?v= Yr1YnOVG-4g杰里·凯恩博士(斯坦福大学介绍系统讲座 – 7)时间:36:00

以前的答案已经很好地说明了技术差异。 还应注意实际的差异:

Memcpy将需要大约两倍的内存来执行相同的任务,但是memmove可能比memcpy花费更长的时间。

例:

假设你在内存中有100个项目的列表,占用100MB的内存。 你想放弃第一个项目,所以你只有99。

Memcpy将需要原始的100 MB和99个的99个项目的额外的99 MB。 总共需要大约199 MB来执行操作,但应该非常快。

Memmove,在最糟糕的情况下将需要原来的100 MB,并将每次移动每个项目1内存地址。 这只需要原来的100MB,但是会比Memcpy慢得多。

当然,创build一个指向列表中第二项的新指针将达到同样的效果,即从列表中删除第一项,但是该示例很好地显示了memcpy和memmove之间的差异。

– 编辑,以帮助澄清我的快乐回答 –
是的,memcpy()和memmove()的实现在内存使用方面可能没有区别(我真的不知道),但是如何使用它们将极大地影响程序的内存使用。 这就是我的意思是memcpy()和memmove()的实际区别。

 int SIZE = 100; Item *ptr_item = (Item *) malloc(size_of(Item) * SIZE); Item *ptr_src_item = ptr_item + 1; Item *ptr_dst_item = ptr_item; memmove(ptr_dst_item, ptr_src_item, SIZE - 1); 

这会创build你的第一个项目丢失的项目列表。 这基本上不需要为程序分配原始ptr_item内存块的内存。 你不能这样做使用memcpy()…如果你这样做,你的程序将需要分配大约两倍的内存。

 int SIZE = 100; Item *ptr_src_item = (Item *) malloc(size_of(Item) * SIZE); Item *ptr_dst_item = (Item *) malloc(size_of(Item) * (SIZE - 1)); memcpy(ptr_dst_item, ptr_src_item, SIZE - 1); 

在第二个代码块中,程序需要的内存是第一个块的两倍。 但是,第二块应该比第一块块快得多,尤其是在SIZE增加的情况下。

这就是我试图解释两者之间的实际差异……但也许我错了呢?