C内存重叠问题,memcpy,memmov,strcpy

8 篇文章 0 订阅
5 篇文章 0 订阅

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

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

针对第一种交叉情况情况,dst<=src且dst+count>src,memcpy和memmove的结果是一样的。请看下面的例子讲解:
int a[] = {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 a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
memcpy(a+4, a, sizeof(int)*6) 结果按照分析应该是:0123012301

但是在vs2005上运行却是:0123012345(有知道的,请告诉我原因)

memmove(a+4, a, sizeof(int)*6) 结果是:0123012345

总结:

1. 当 src 和 dest 所指内存区有重叠时,memmove 相对 memcpy 能提供保证:保证能将 src 所指内存区的前 n 个字节正确的拷贝到 dest 所指内存中;
2. 当 src 地址比 dest 地址低时,两者结果一样。换句话说,memmove 与 memcpy 的区别仅仅体现在 dest 的头部和 src 的尾部有重叠的情况下;


3.下面来看下memmove函数的原型写法:

void *memmove(void *dest, const void *source, size_t count)
{
assert((NULL != dest) && (NULL != source));
char *tmp_source, *tmp_dest;
tmp_source = (char *)source;
tmp_dest = (char *)dest;
if((dest<=source) || (source + count) <=dest))
{// 如果没有重叠区域
while(count--)
*tmp_dest++ = *tmp_source++;
}
else
{ //如果有重叠(反向拷贝)
tmp_source += count - 1;
tmp_dest += count - 1;
while(count--)
*--tmp_dest = *--tmp;
}
return dest;
}


考虑了内存重叠的内存拷贝函数 memcpy 相当于memmove

考虑内存重叠的字符串拷贝函数strcpy

char * strcpy(char *dest, const char *src)

{

    char *d = dest; //backup input

    char *s = src;

    int count = 0;

    assert(dest); //非空指针检查

    assert(src);

    if(src == dest)

         return src;

    count = strlen(src) + 1;//src length

    if(count<=1)

         return 0; //empty src

    if(dest<=src || dest>(src+count))

    {

         while(count--)

             *d++ = *s++;

    }

    else //dest 位于src+count中间,

    {

         d = dest+count;

         s = src+count;

         while(count--)

             *d-- = *s--; //倒过来拷贝

    }


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值