C语言:内存重叠问题

本文通过一个例子来说明一下关于 内存重叠问题的分析与解决方案,大家一起学习学习吧。
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)当源内存的首地址小于目标内存的首地址时,实行反向拷贝

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值