You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

当src与dst内存重叠时,指针循环复制为何与memmove效果不同?

内存重叠时手动循环复制与memmove执行效果差异的原因

先看你给出的两段代码:
手动循环复制代码:

for (int i = 0; i < size; i++) {
    dst[i] = src[i];
}

memmove调用代码:

memmove(dst, src, size);

两者执行效果的差异,核心在于内存重叠场景下的复制顺序逻辑不同:

1. 手动循环的复制逻辑

手动循环是固定从内存低地址到高地址依次复制,也就是按索引从0到size-1的顺序,把src[i]的值赋给dst[i]。这种顺序在内存区域重叠时,会出现“还没读取的src数据被提前覆盖”的问题:

举个具体例子:假设我们有数组int arr[] = {1, 2, 3, 4};,src = arr(指向数组起始地址),dst = arr + 1(指向数组第2个元素的地址),size = 3。手动循环的执行过程:

  • i=0:dst[0] = src[0] → arr[1]被改成1,数组变为{1, 1, 3, 4}
  • i=1:dst[1] = src[1] → 此时src[1]已经是被修改后的1,arr[2]被改成1,数组变为{1, 1, 1, 4}
  • i=2:dst[2] = src[2] → src[2]已经是被修改后的1,arr[3]被改成1,最终数组变成{1, 1, 1, 1}

这显然不是预期的结果——我们原本想把arr的前3个元素1,2,3复制到从第2个元素开始的位置,得到{1,1,2,3},但手动循环因为顺序问题破坏了原始数据。

2. memmove的处理逻辑

memmove内部会先判断src和dst的内存地址关系,自动调整复制顺序:

  • 如果dst的起始地址在src前面,或者两者无重叠,就用和手动循环一致的低地址到高地址顺序复制;
  • 如果dst的起始地址在src后面且存在重叠(即src < dst < src + size),就会改用高地址到低地址的顺序复制,也就是从索引size-1开始倒着复制,避免覆盖还未读取的src原始数据。

还是用刚才的例子,memmove的执行过程:

  • i=2:dst[2] = src[2] → arr[3]被改成3,数组变为{1, 2, 3, 3}
  • i=1:dst[1] = src[1] → arr[2]被改成2,数组变为{1, 2, 2, 3}
  • i=0:dst[0] = src[0] → arr[1]被改成1,最终数组变成{1, 1, 2, 3},完全符合预期。

简单来说,手动循环是“一根筋”从前往后复制,不管内存重叠情况;而memmove会根据内存布局智能调整复制方向,确保重叠区域的原始数据不会被提前覆盖。

内容的提问来源于stack exchange,提问作者Yanir

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 16:42:44