请查看重叠内存块的memcpy()的这种莫名其妙的行为和输出

在阅读了关于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  #include  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+15位置的字符复制到str+20位置(覆盖那里的内容)来开始复制,字符在str+16位置到str+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.

这究竟是什么?是不是真正用于memmove()的中间缓冲区?

如果对象重叠,则memcpy的行为未定义。 试图推断未定义的行为是没有意义的。 由于它是未定义的,它无视理由。 您了解规则,并且它们已清楚地记录在案。 如果对象重叠,请使用memmove。

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