各种各样的标准库函数在将字节序列从一个存储区复制到另一个存储区的作用之中。当源区域和目标区域重叠时,这些功能大多数都具有不确定的行为。
例如,这...
#include <string.h> /* for memcpy() */ char str[19] = "This is an example"; memcpy(str + 7, str, 10);
...尝试复制10个字节,其中源和目标存储区重叠三个字节。可视化:
overlapping area | _ _ | | v v T h i s i s a n e x a m p l e \0 ^ ^ | | | destination | source
由于存在重叠,因此导致的行为是不确定的。
其中有这样的限制标准库函数memcpy(),strcpy(),strcat(),sprintf(),和sscanf()。该标准说明了这些功能以及其他几个功能:
如果在重叠的对象之间进行复制,则行为是不确定的。
该memmove()函数是该规则的主要例外。它的定义指定该函数的行为就像首先将源数据复制到一个临时缓冲区中,然后将其写入目标地址一样。重叠的源区域和目标区域也不例外,也不需要任何区域,因此memmove()在这种情况下定义良好的行为也是如此。
这种区别反映了效率VS。一般性权衡。诸如这些功能执行的复制通常发生在不相交的内存区域之间,并且经常有可能在开发时知道特定的内存复制实例是否属于该类别。假设非重叠提供了相对更有效的实现,当假设不成立时,这些实现不会可靠地产生正确的结果。允许大多数C库函数更有效的实现,并memmove()填补空白,以解决源和目标可能重叠或确实重叠的情况。为了在所有情况下都能产生正确的效果,它必须执行其他测试和/或采用效率相对较低的实现。