memcopy和memmove 区别

 1.memmove

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

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

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

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

  

  1. void *MemMove(void *dest,const void *src,size_t n)  
  2. {  
  3.     if(n == 0)  
  4.         return 0;  
  5.     if(dest == NULL)  
  6.         return 0;  
  7.     if(src == NULL)  
  8.         return 0;  
  9.     char *psrc = (char*)src;  
  10.     char *pdest = (char*)dest;  
  11.     //检查是否有重叠问题  
  12.     if((dest <= psrc) || (pdest >= psrc+n))  
  13.     {     
  14.         //正向拷贝--Non-Overlapping Buffers copy from lower addresses to higher addresses    
  15.         for(int i=0;i<n;i++)  
  16.         {  
  17.             *pdest = *psrc;  
  18.             psrc++;  
  19.             pdest++;  
  20.         }  
  21.     }  
  22.     else  
  23.     {  
  24.         //反向拷贝--Overlapping Buffers copy from higher addresses to lower addresses     
  25.         psrc += n;  
  26.         pdest += n;  
  27.         for(int i=0;i<n;i++)  
  28.         {  
  29.             psrc--;  
  30.             pdest--;  
  31.             *pdest = *psrc;  
  32.         }  
  33.     }  
  34.     return dest;  
  35. }  
 

 

2.memcpy

 

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

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

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

 

 

  1. void *MemCopy(void *dest,const void *src,size_t n)  
  2. {  
  3.     if(NULL == dest)  
  4.         return 0;  
  5.     if(NULL == src)  
  6.         return 0;  
  7.     char *pdest = (char*)dest;  
  8.     char *psrc = (char*)src;  
  9.     while(n--) //不对是否存在重叠区域进行判断  
  10.         *pdest++ = *psrc++; //*pdest++相当于*(pdest++)--先取*pdest,再pdest++  
  11.     return dest;  
  12. }  

   

 

3.两者区别

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

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

    

测试程序(其中用到了上面的两个函数及对应的库函数):

 

  1. //该程序在gcc下编译验证  
  2. #include <string.h>    
  3. #include <stdio.h>   
  4.   
  5. int main()    
  6. {    
  7.     int a[10];    
  8.     for(int i=0; i < 10; i++)    
  9.         a[i] = i;    
  10.     MemCopy(&a[4],a,sizeof(int)*6);    //结果为:0 1 2 3 0 1 2 3 0 1  
  11.     //memcpy(&a[4], a, sizeof(int)*6); //结果为:0 1 2 3 0 1 2 3 0 1(vc下和下面一个相同)   
  12.     //MemMove(&a[4],a,sizeof(int)*6);  //结果为:0 1 2 3 0 1 2 3 4 5  
  13.     //memmove(&a[4],a,sizeof(int)*6);  //结果为:0 1 2 3 0 1 2 3 4 5     
  14.     //MemMove(a,&a[4],sizeof(int)*6);  //结果为:4 5 6 7 8 9 6 7 8 9   
  15.     //memmove(a, &a[4], sizeof(int)*6);//结果为:4 5 6 7 8 9 6 7 8 9     
  16.     //memcpy(a, &a[4], sizeof(int)*6); //结果为:4 5 6 7 8 9 6 7 8 9   
  17.     //MemCopy(a,&a[4],sizeof(int)*6);  //结果为:4 5 6 7 8 9 6 7 8 9   
  18.     for(i = 0; i < 10; i++)    
  19.         printf("%d ",a[i]);    
  20.     printf("/n");    
  21.     return 0;    
  22. }   

  

 

  

程序分析:

 这两个函数的函数原型(除了名字)是一样的:
void *memcpy(void *dst, const void *src, size_t count):
void *memmove(void *dst, const void *src, size_t count);
它们都是从src所指向的内存中复制count个字节到dst所指内存中,并返回dst的值。当源内存区域和目标内存区域无交叉时,两者的结果都是一样的。但有交叉时不一样。源内存和目标内存交叉的情况有以下两种:(左边为低地址)

 

1、


即:dst<=src 且 dst+count>src

2、


即:src<dst且src+count>dst
下面将针对这两种情况来讨论。针对第一种交叉情况情况,dst<src且dst+count>src,memcpy和memmove的结果是一样的。请看下面的例子讲解:
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
memcpy(a, a+4, sizeof(int)*6);和memmove(a, a+4, sizeof(int)*6);结果是:
4567896789



针对第二种情况,src<dst且src+count>dst,memcpy和memmove的结果是不一样的。请看下面的例子:
int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
memcpy(a+4, a, sizeof(int)*6)


memmove(a+4, a, sizeof(int)*6)


 



上面图示来自 http://hi.baidu.com/lkmoses/blog/item/3c553dc4778701169c163d57.html
 

 

 

总结:

两者的功能基本相同,唯一不同的是,当 dest 和 src 有重叠的时候选用不同的函数可能会造成不同的结果。
     对比上面执行结果,不难得出以下结论:
1. 当 src 和 dest 所指内存区有重叠时,memmove 相对 memcpy 能提供保证:保证能将 src 所指内存区的前 n 个字节正确的拷贝到 dest 所指内存中;
2. 当 src 地址比 dest 地址低时,两者结果一样。换句话说,memmove 与 memcpy 的区别仅仅体现在 dest 的头部和 src 的尾部有重叠的情况下;

                即:从高向低复制都可以,从低向高复制用memmove() 

memcpy的返回值设计成void   *是有目的的,是便于嵌套使用memcpy、memmove等函数。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值