分析拷贝过程中发生的重叠问题

关于内存重叠问题,我们先来看一道例题:

我们在做道题的时候,会发现有多种情况,有前面的部分拷到后面,有后面的部分拷贝到前面,有的部分长,有部分短,有从前往后拷贝,有从后往前拷贝,有内存重叠,也有不重叠······

看似复杂无比,其实不然,下面我们来分析所有情况总结规律。

所有情况总结一下就是:

拷贝方法有两种:a.从前往后拷贝。

                                b.从后往前拷贝。

内容分布有两种情况:

一:没有内存重叠:

  1. src在前des在后,即前面的内容拷贝到后面。方法a和b都能用。
  2. des在前src在后,即后面的内容拷贝到前面。方法a和b都能用。

二:有内存重叠:

  1. src在前des在后。只能用方法b。
  2. des在前src在后。只能用方法a。

 

下面画图说明,更加形象易懂。(src、des为指针,len为要拷贝内容的长度)

情况一.(1):(des>src && src+len<=des)

将前面以src开始的一小段移动到des为开头的一小段。(src、des为指针。)

方法a:从前往后拷贝。即*src->*des,然后src++,des++。

方法b:从后往前拷贝。即src这一段的结尾移动到des这一段的结尾,然后结尾依次减减。

 

情况一.(2):(src >des && des+len<=src)

方法同上。既可以从前往后,也可以从后往前拷贝。

 

 

情况二.(1):src在前,绿色部分内容拷贝到红色部分。有重叠(红绿重叠在一起的部分即重叠)

我们可以看到,将src开头的绿色部分移动到des开头的后半部分会出现重叠问题,这时只能从后往前拷贝。即将绿色部分的最右边单元拷贝到红色部分的最右边单元,红色绿色的结尾依次减减。

 

情况二.(2):des在前,src在后,绿色部分内容拷贝到红色部分。有重叠。

 

这时,从前往后拷贝。即*src拷到*des,然后src++,des++

 

代码如下:

#include<stdio.h>

 

void MoveStr(int *src,int *des,int len)//len为以src开头的字符串长度

{

   int i;

   if(src < des && src + len <= des ||des < src && des + len <= src)//没有内存重叠

   {

      for(i = 0;i < len;i++)

      {

        des[i] = src[i];

      }

   }

   else//有内存重叠的情况。又分2个情况

   {

      if(src < des)//此情况从后往前

      {

        for(int i = len - 1;i >= 0;i--)

        {

           des[i] = src[i];

        }

      }

      else//此情况从前往后

      {

        for(int i = 0;i < len;i++)

        {

           des[i] = src[i];

        }

      }

   }

}

void Show(int *arr,int len)

{

   for(int i=0;i<len;i++)

   {

      printf("%d ",arr[i]);

   }

   printf("\n");

}

int main()

{

   int str[10] = {1,2,3,4,5,6,7,8,9,10};

   MoveStr(str,&str[5],5);

   Show(str,sizeof(str)/sizeof(str[0]));

   return 0;

}

运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值