浅聊内存重叠

来源:互联网 发布:php socket 编辑:程序博客网 时间:2024/05/22 06:14


内存重叠:拷贝的目标地址在源地址范围内,即拷贝的目标地址和源地址有重叠。

就一个例子来进行展开:

现有一整型数组arr[10] = {1,2,3,4,5,6,7,8,9,10},要求将其拷贝到整形数组brr[10]当中去,这是很简单的,类似于字符串的拷贝,但是同时又与之有区别。如果现在我们选择将从arr[4]开始将6个元素拷贝到从arr[0]开始的位置,这样将会出现怎样的结果呢?再有,选择将从arr[0]开始的6个元素拷贝到从arr[4]开始的位置,又该怎样呢?这两个问题就引出了“内存重叠”的话题了。

 从第一个问题开始分析。

我们可以看到,中间的arr[4]arr[5]是重叠部分,这时的拷贝方式是从前往后拷贝的,与字符串的拷贝方式并没有多大差别,可是,再想想,如果从arr[9]开始从后往前拷贝呢?那么这时,arr[4]arr[5]arr[8]arr[9]覆盖,那么arr[4]arr[5]的数据被覆盖了,显然得到的结果就不是我们想要的了。

正确结果(标红的地方)及图如下(图中的数字表示的是下标)


void Move(int *des,int *src,int len)//len是要拷贝的src的个数

{

        if(des>src&& (src+len) > des) //出现内存重叠

        {

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

                  {

                           des[i]= src[i];//从后面开始拷贝

                  }

        }

        else if(des<=src && des+len > src)//出现内存重叠

        {

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

                  {

                           des[i] = src[i];//从前面开始拷贝

                  }

        }

}

 

Int main()

{

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

Move(&arr[0],&arr[4],6);

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

{

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

}

 

return 0;

}

程序结果如下:


 

再看第二个问题,中间的arr[4]arr[5]是重叠部分,这时的拷贝方式是从后往前拷贝的,这就要与上面的情况有所区分了。如果采用从前往后的拷贝方式的话arr[4]arr[5]将被arr[0]arr[1]给覆盖掉,所以从后往前拷贝可以避免这个问题,在最后才给arr[4]arr[5]赋值。

正确结果(标红的地方)及图如下(图中的数字表示的是下标)


 

void Move(int *des,int *src,int len)//len是要拷贝的src的个数

{

        if(des>src && (src+len) > des) //出现内存重叠

        {

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

                  {

                           des[i] = src[i];//从后面开始拷贝

                  }

        }

        else if(des<=src && des+len> src)//出现内存重叠

        {

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

                  {

                           des[i]= src[i];//从前面开始拷贝

                  }

        }

}

 

Int main()

{

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

        Move(&arr[4],&arr[0],6);

        for(inti=0;i<10;i++)

        {

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

        }

return 0;

}

程序结果如下:


 

所以最后总结得:发生内存重叠有两种情况。

  1. des>src && (src+len)> des:从后往前拷贝。

  2. des<=src && des+len > src:从前往后拷贝。

     

以上内容是我的一些比较浅显的归纳,在查找资料的时候,有看到关于srecpy()memmove()的内容,日后有机会我也会进行补充。