本文通过一个例子来说明一下关于
内存重叠问题的分析与解决方案,大家一起学习学习吧。
1.题目:有n个整数,使前面各数顺序向后移m个位置,最后m个数变成最前面m个数。如下图:
void Move(int *arr, int n, int m)//n表示数组长度,m表示需要移到的后半段的数据长度
{
if(arr ==NULL || n <= 0 || m < 0 || n < m)//首先是判断满足题目的条件
{
return;
}
int *p =(int *)malloc(m * sizeof(int));//创建动态内存,将后m个数据复制过去
int i;
for(i = 0; i< m; i++)
{
p[i] = arr[n- m + i];
}
for(i = n - m - 1; i >= 0;i--)//将前面(n-m)个数据向后移 ( 解决方案)
{
arr[i + m] =arr[i];
}
for(i = 0; i< m; i++)//将后m个数据复制到前面
{
arr[i] =p[i];
}
free(p);//释放内存p
}
1.题目:有n个整数,使前面各数顺序向后移m个位置,最后m个数变成最前面m个数。如下图:
void Move(int *arr, int n, int m)//n表示数组长度,m表示需要移到的后半段的数据长度
{
if(arr ==NULL || n <= 0 || m < 0 || n < m)//首先是判断满足题目的条件
{
return;
}
int *p =(int *)malloc(m * sizeof(int));//创建动态内存,将后m个数据复制过去
int i;
for(i = 0; i< m; i++)
{
p[i] = arr[n- m + i];
}
for(i = n - m - 1; i >= 0;i--)//将前面(n-m)个数据向后移 ( 解决方案)
{
arr[i + m] =arr[i];
}
for(i = 0; i< m; i++)//将后m个数据复制到前面
{
arr[i] =p[i];
}
free(p);//释放内存p
}
在上面绿色段的过程就有可能出现内存重叠问题,看下面代码
for(i = 0; i < n -m; i++)
{
arr[i + m] =arr[i];
}
如果上面代码改为红色代码,程序运行结果会是:1 2 3 1 2 3 1
2.内存重叠问题列举
当数组进行拷贝的时候,如果是在同一个数组内拷贝,就有可能出现内存重叠的问题。
void Move2(int *des, int *src, intlen)//从src拷贝到des,len是需要拷贝的数据个数
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()
{
//(1)从一个数组拷贝到另一个数组,ok
int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
intbrr[10];
Move2(brr,arr, 10);
Show(arr,sizeof(arr) / sizeof(arr[0]));
Show(brr,sizeof(brr) / sizeof(brr[0]));
//(2)内存重叠1,ok
int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Move2(&arr[0], &arr[3], 7);
Show(arr,sizeof(arr) / sizeof(arr[0]));
//(3)内存重叠2,error
intarr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Move2(&arr[3], &arr[0], 7);
Show(arr,sizeof(arr) /sizeof(arr[0]));
return 0;
}
上面程序的运行结果分别是:
(1) 1 2 3 4 5 6 7 8 910
(2) 4 5 6 7 89 10 8 9 10
(3) 1 2 3 1 2 3 1 2 3 1
分析错误③:
在
a[0]复制到a[3]过程中,将原来a[3]的值覆盖,后面依次覆盖a[4]、a[5]…,使得运行结果和预想不一致。
3.处理措施:
如何判断有内存重叠问题?
看地址,看目标地址和源地址。
(1)当源内存的首地址大于目标内存的首地址时,实行正向拷贝;
(2)当源内存的首地址小于目标内存的首地址时,实行反向拷贝 。
for(i = 0; i < n -m; i++)
{
arr[i + m] =arr[i];
}
如果上面代码改为红色代码,程序运行结果会是:1 2 3 1 2 3 1
2.内存重叠问题列举
当数组进行拷贝的时候,如果是在同一个数组内拷贝,就有可能出现内存重叠的问题。
void Move2(int *des, int *src, intlen)//从src拷贝到des,len是需要拷贝的数据个数
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()
{
//(1)从一个数组拷贝到另一个数组,ok
int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
intbrr[10];
Move2(brr,arr, 10);
Show(arr,sizeof(arr) / sizeof(arr[0]));
Show(brr,sizeof(brr) / sizeof(brr[0]));
//(2)内存重叠1,ok
int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Move2(&arr[0], &arr[3], 7);
Show(arr,sizeof(arr) / sizeof(arr[0]));
//(3)内存重叠2,error
intarr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Move2(&arr[3], &arr[0], 7);
Show(arr,sizeof(arr) /sizeof(arr[0]));
return 0;
}
上面程序的运行结果分别是:
(1) 1 2 3 4 5 6 7 8 910
(2) 4 5 6 7 89 10 8 9 10
(3) 1 2 3 1 2 3 1 2 3 1
分析错误③:
3.处理措施:
如何判断有内存重叠问题?
看地址,看目标地址和源地址。
(1)当源内存的首地址大于目标内存的首地址时,实行正向拷贝;
(2)当源内存的首地址小于目标内存的首地址时,实行反向拷贝 。