关于内存重叠问题,我们先来看一道例题:
我们在做道题的时候,会发现有多种情况,有前面的部分拷到后面,有后面的部分拷贝到前面,有的部分长,有部分短,有从前往后拷贝,有从后往前拷贝,有内存重叠,也有不重叠······
看似复杂无比,其实不然,下面我们来分析所有情况总结规律。
所有情况总结一下就是:
拷贝方法有两种:a.从前往后拷贝。
b.从后往前拷贝。
内容分布有两种情况:
一:没有内存重叠:
- src在前des在后,即前面的内容拷贝到后面。方法a和b都能用。
- des在前src在后,即后面的内容拷贝到前面。方法a和b都能用。
二:有内存重叠:
- src在前des在后。只能用方法b。
- 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;
}
运行结果: