-1

阅读以下内容后memcpy(),我继续阅读memmove()

To avoid overflows, the size of the arrays pointed by both the destination and source parameters, shall be at least num bytes, and should not overlap (for overlapping memory blocks, memmove is a safer approach).(关联)

在检查了用于说明其工作的程序后,memmove()我决定memcpy()改用它来调整它,以查看输出有何不同。令我惊讶的是,即使是内存块重叠的情况,它们也是相同的。这是程序和输出,然后我开始描述我的困惑:

#include <stdio.h>
#include <string.h>

int main ()
{
  char str[] = "memmove can be very useful......";
  //memmove (str+20,str+15,11);
  memcpy(str+20,str+15,11);  //Simply used memcpy instead of memmove
  puts (str);
  return 0;
}

输出 memmove can be very very useful.

此输出与 . 的输出相同memmove()。这是我的困惑:

1)为什么两者的输出相同?由于在 的情况下没有使用中间缓冲区memcpy(),我希望复制从将位置中的字符复制str+15str+20位置(覆盖那里的内容)开始,将位置中的字符复制str+16str+21位置,等等直到str+20 位置的字符,现在已更改为 str+15 位置的字符,要复制到 str+25 位置。但事实并非如此,没有覆盖,它就像一个中间缓冲区用于编写确切的原始字符串。这是一个插图:

memmove can be very useful......  //Original positions before memcopy
               ^    ^
            str+15  str+20

memmove can be very vseful......
                    ^ copies str+15 to str+20

memmove can be very veeful......
                     ^ copies str+16 to str+21
memmove can be very verful......
                      ^ copies str+17 to str+22
memmove can be very veryul......
                       ^copies str+18 to str+23
memmove can be very very l......
                        ^ copies str+19 to str+24
memmove can be very very v......
                         ^ I expect 'v' to be copied from str+20 to str+25
                           as str+20  now has 'v',not 'u'
memmove can be very very ve.....
                          ^ I expect 'e' to be copied from str+21 to str+26 
                            as str+21 now has 'e' not 's'

那么为什么 memcpy() 将其复制为memmove 会非常有用,而不是memmove 可以非常非常非常 v呢?

2)现在产生一个次要的次要问题。以下是关于memmove()LINK

Copying takes place as if an intermediate buffer were used, allowing the destination and source to overlap.

这里到底是什么as if?中间缓冲区不是真的用于memmove()吗?

4

1 回答 1

6

如果对象重叠,则 memcpy 的行为未定义。试图推理未定义的行为毫无意义。由于它是未定义的,它无视理性。你知道这些规则,而且它们都被清楚地记录在案。如果对象重叠,请使用 memmove。

至于“好像”的使用,即指定行为但不限制实现。这允许库实现者使用他们认为合适的任何方法,只要最终结果与使用中间缓冲区相同。例如,实现可以检测到对象不重叠,因此出于性能原因避免使用中间缓冲区。

于 2013-05-14T05:37:07.703 回答