【问题标题】:memmove implementation in CC 中的 memmove 实现
【发布时间】:2011-04-04 02:13:04
【问题描述】:

谁能帮我理解 memmove 是如何在 C 中实现的。我只有一个特殊条件对吗?

if((src<dst)&&((src+sz) > dst))

copy from the back

还取决于堆栈的增长方式吗?

【问题讨论】:

  • 如果srcdstsz都是正值,则条件不满足。如果src &gt; dst,添加积极的sz 不会减少它。
  • 我一直有疑问。可以像您一样比较地址吗?我在某处听说它们不能存在,除非它们属于相同的数组或结构。有人请澄清!

标签: c memmove


【解决方案1】:

从数学上讲,您根本不必担心它们是否重叠。如果src 小于dst,则从末尾复制。如果src 大于dst,则从头开始复制。

如果srcdst 相等,则直接退出。

那是因为您的案例属于以下情况之一:

1) <-----s----->                start at end of s
                 <-----d----->

2) <-----s----->                start at end of s
            <-----d----->

3) <-----s----->                no action
   <-----d----->

4)          <-----s----->       start at beginning of s
   <-----d----->

5)               <-----s----->  start at beginning of s
   <-----d----->

即使没有重叠,它仍然可以正常工作,并简化您的条件。

如果您有比向后复制更有效的方法来向前复制,那么是的,您应该检查重叠以确保尽可能使用更有效的方法。换句话说,将上面的选项 1 更改为从头开始复制。

【讨论】:

  • 请注意,这里还有一个隐藏的假设,即您一次只复制一个字节。
  • 好吧,无论你一次复制一个字节,还是一个四字或一些海量的 SSE9 1024 位超字值,理论都是一样的。您必须确保没有将复制到您尚未复制的重叠区域。引入的所有 N-is-wider-than-char 选项都是在不是 N 值的直接倍数的情况下对重叠(和最终转移)进行更复杂的检测。
  • @caf: 如果srcdest 在您可以复制的较大类型方面具有相同的对齐方式,那么您永远不必担心破坏您尚未复制的区域,因为位置总是至少相差那个大小。如果它们不共享相同的对齐方式,那么无论如何您都会被困在以字节形式复制...除非您想使用一些讨厌的 x86 未对齐 io...
  • @R..:在许多系统上,至少如果一个人使用的是一种理智的 C 方言,它允许一个人绕过别名限制,那么改变对齐方式的复制操作仍然可以通过读取和写入来完成一次多个单词,如果例如抓取一个字并提取部分,然后在每次循环时读取(例如)四个 32 位寄存器,移位它们,与部分字组合,并抓取掉出来的位,然后存储四个 32 位寄存器等。在许多 ARM 处理器上,即使在未对齐的情况下,性能仍然可以是使用字节的两倍。
  • @R..:例如,在 ARM7-TDMI 上,不计算循环开销,使用对齐校正代码复制每组四个字需要 20 个周期。如果没有对齐校正,则需要 12 个。单独复制字节或字每个需要 5 个周期。在任何情况下都不需要未对齐的访问(ARM7-TDMI 不支持)。
【解决方案2】:

memmove 如果两个内存区域不重叠,则可以转换为 memcpy。显然,memcpy 在大多数系统上都经过了极大的优化(我使用的其中一个几乎利用了书中从展开循环到支持最大吞吐量的 SSE 操作的所有技巧)。

如果两个内存区域确实重叠,则出于所有意图和目的,将要复制的区域移动到临时缓冲区中,并将临时缓冲区(最有可能全部使用 memcpy)复制回原始缓冲区的顶部。您不能从头开始工作或在重叠区域的后面工作,因为在此过程中您总是会导致至少有一些数据被损坏。

话虽这么说,我已经很久没有看 libc 代码了,所以可能有一个我还没有想到的 memmove 和重叠区域的优化。

memmove 完全不依赖于堆栈的增长方式 - 它只是将内存的一个区域复制到另一个位置 - 与 memcpy 完全一样,除了它处理重叠区域而 memcpy 不处理。

编辑:实际上,再想一想...如果您从正确的“来源”(可以这么说)出发,从后面工作可以工作,这取决于移动本身(例如,是否是 source here,并且 tt 的评论也相当不错。

【讨论】:

    【解决方案3】:

    取决于编译器。好的编译器会根据目标处理器指令集和总线宽度使用好的优化。

    【讨论】:

    • 我认为这应该进入评论而不是单独回复
    猜你喜欢
    • 2021-01-20
    • 1970-01-01
    • 2021-03-03
    • 2021-09-26
    • 2013-11-05
    • 2012-10-31
    • 2018-09-02
    • 1970-01-01
    • 2011-04-30
    相关资源
    最近更新 更多