memcopy函数和memmove函数

memcpy:指的是c和c++使用的内存拷贝函数,memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。

函数原型:void *memcpy(void *dest, const void *src, size_t n);

memmove:memmove用于从src拷贝count个字节到dest,如果目标区域和源区域有重叠的话,memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中。但复制后src内容会被更改。但是当目标区域与源区域没有重叠则和memcpy函数功能相同。

函数原型:void *memmove(void *dst, const void *src, size_t count); 

两者区别:

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

总结:两者的功能基本相同,唯一不同的是,当 dest 和 src 有重叠的时候选用不同的函数可能会造成不同的结果。

1. 当 src 和 dest 所指内存区有重叠时,memmove 相对 memcpy 能提供保证能将 src 所指内存区的前 n 个字节正确的拷贝到 dest 所指内存中;

2. 当 src 地址比 dest 地址低时,两者结果一样。换句话说,memmove 与 memcpy 的区别仅仅体现在 dest 的头部和 src 的尾部有重叠的情况下;

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

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

两者的实现:

《一》memmove

void *MemMove(void *dest,const void *src,size_t n)  
{  
    if(n == 0)  
        return 0;  
    if(dest == NULL)  
        return 0;  
    if(src == NULL)  
        return 0;  
    char *psrc = (char*)src;  
    char *pdest = (char*)dest;  
    //检查是否有重叠问题  
    if((dest <= psrc) || (pdest >= psrc+n))  
    {       
        for(int i=0;i<n;i++)  
        {  
            *pdest = *psrc;  
            psrc++;  
            pdest++;  
        }  
    }  
    else 
    {     
        psrc += n;  
        pdest += n;  
        for(int i=0;i<n;i++)  
        {  
            psrc--;  
            pdest--;  
            *pdest = *psrc;  
        }  
    }  
    return dest;  
} 

《二》memcopy

void *MemCopy(void *dest,const void *src,size_t n)  
{  
    if(NULL == dest)  
        return 0;  
    if(NULL == src)  
        return 0;  
    char *pdest = (char*)dest;  
    char *psrc = (char*)src;  
    while(n--) //不对是否存在重叠区域进行判断  
    {
        *pdest++ = *psrc++; 
    } 
    return dest;  
} 

要想安全的使用memcopy函数,必须要解决内存重叠。所以最完美的解决方案还是判断源地址和目的地址的大小,才决定到底是从高地址开始拷贝还是低地址开始拷贝。改进后的代码如下:

void * MyMemMove(void *dst,const void *src,int count)
{
     assert(dst);
     assert(src);
     void * ret = dst;
     char *psrc = (char*)src;  
     char *pdest = (char*)dest; 
     //判断是否有内存重叠
     if (pdest<= psrc || pdest>= (psrc+ count)) {
        
         while (count--) {
             *pdest= *psrc;
             pdest++;
             psrc++;
         }
      }
      else {
         
          pdest= pdest+ count - 1;
          psrc= psrc+ count - 1;
 
          while (count--) {
          *pdest= *psrc;
          pdest--;
          psrc--;
       }
    }
    return(ret);
}

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值