menmove()和mencpy()的区别

1.memmove

函数原型:void *memmove(void *dest, const void *source, size_t count)

返回值说明:返回指向dest的void *指针

参数说明:dest,source分别为目标串和源串的首地址。count为要移动的字符的个数

函数说明:memmove用于从source拷贝count个字符到dest,如果目标区域和源区域有重叠的话,memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中。

 

2.memcpy

函数原型:void *memcpy(void *dest, const void *source, size_t count);

返回值说明:返回指向dest的void *指针

函数说明:memcpy功能和memmove相同,但是memcpy中dest和source中的区域不能重叠,否则会出现未知结果。

 

3.两者区别

 函数memcpy()从source指向的区域向dest指向的区域复制count个字符,如果两数组重叠,不定义该函数的行为。

而memmove(),如果两函数重叠,赋值仍正确进行。

memcpy函数假设要复制的内存区域不存在重叠,如果你能确保你进行复制操作的的内存区域没有任何重叠,可以直接用memcpy;如果你不能保证是否有重叠,为了确保复制的正确性,你必须用memmove。

memcpy的效率会比memmove高一些,如果还不明白的话可以看一些两者的实现:

1.  memcpy

2.  代码: 
;***
;memcpy.asm - contains memcpy and memmove routines
;
;       Copyright (c) 1986-1997, Microsoft Corporation. All right reserved.
;
;Purpose:
;       memcpy() copies a source memory buffer to a destination buffer.
;       Overlapping buffers are not treated specially, so propogation may occur.
;       memmove() copies a source memory buffer to a destination buffer.
;       Overlapping buffers are treated specially, to avoid propogation.
;
;*******************************************************************************
;***
;memcpy - Copy source buffer to destination buffer
;
;Purpose:
;       memcpy() copies a source memory buffer to a destination memory buffer.
;       This routine does NOT recognize overlapping buffers, and thus can lead
;       to propogation.
;       For cases where propogation must be avoided, memmove() must be used.
;
;       Algorithm:

  1.        void* memcpy(void* dest, void* source, size_t count)
  2.       {
  3.       assert(NULL != source && NULL != dest);
  4.            void* ret = dest;
  5.           //copy from lower address to higher address
  6.           while (count--)
  7.                   *dest++ = *source;

10.  

  1. 11.            return ret;
  2. 12.       }

13.  

14. memmove

15. memmove - Copy source buffer to destination buffer
;
;Purpose:
;       memmove() copies a source memory buffer to a destination memory buffer.
;       This routine recognize overlapping buffers to avoid propogation.
;       For cases where propogation is not a problem, memcpy() can be used.
;
;   Algorithm:

  1. 16.     void* memmove(void* dest, void* source, size_t count)
  2. 17.    {
  3. 18.     assert(NULL != source && NULL != dest);
  4. 19.        void* ret = dest;

20.  

  1. 21.        if (dest <= source || dest >= (source + count))
  2. 22.        {
  3. 23.           //Non-Overlapping Buffers
             //copy from lower addresses to higher addresses
        
  4. 24.          while (count --)
  5. 25.                *dest++ = *source++;
  6. 26.      }
  7. 27.      else
  8. 28.      {
  9. 29.         //Overlapping Buffers
           //copy from higher addresses to lower addresses
  10. 30.        dest += count - 1;
  11. 31.        source += count - 1;
  12. 32.        while (count--)
  13. 33.                 *dest-- = *source--;
  14. 34.       }
  15. 35.       return ret;
  16. 36.    }

 

区别: 

从DESCRIPTION看来,两者的功能基本相同,唯一不同的是,当 dest 和 src 有重叠的时候选用不同的函数可能会造成不同的结果。不妨写个小程序来测一下:
0 #i nclude <string.h> 
1 #i nclude <stdio.h> 

3 int main() 
4 { 
5    int i = 0; 
6    int a[10]; 
7   
8    for(i; i < 10; i++) 
9    { 
10        a[i] = i; 
11   } 
12 
13   memcpy(&a[4], a, sizeof(int)*6); 
14  
15   for(i = 0; i < 10; i++) 
16   { 
17       printf("%d ",a[i]); 
18   } 
20   
21   printf("\n"); 
22   return 0; 
23 } 
  
很简单的小程序!不过已经足以达到我的目的了:)将上面代码gcc之后再运行,结果为:0 1 2 3 0 1 2 3 0 1 。 
再把第13行改成:memmove(&a[4], a, sizeof(int)*6),重新gcc再运行,结果为:0 1 2 3 0 1 2 3 4 5 ! 
呵呵,两者的区别出现了。不过其实这样还不够,继续修改13行: memmove(a, &a[4], sizeof(int)*6) //也就是将源、目的置换一下而已 
重新gcc编译再运行,结果为:4 5 6 7 8 9 6 7 8 9 。 
还不够,继续修改13行为: memcpy(a, &a[4], sizeof(int)*6); gcc并运行,结果仍为: 4 5 6 7 8 9 6 7 8 9 ! 
至此真相已经大白了。对比上面四个结果,不难得出以下结论: 
1. 当 src 和 dest 所指内存区有重叠时,memmove 相对 memcpy 能提供保证:保证能将 src 所指内存区的前 n 个字节正确的拷贝到 dest 所指内存中; 
2. 当 src 地址比 dest 地址低时,两者结果一样。换句话说,memmove 与 memcpy 的区别仅仅体现在 dest 的头部和 src 的尾部有重叠的情况下。

posted @ 2011-06-15 21:28  ACE封印  Views(1385)  Comments(0Edit  收藏  举报