複製重疊記憶體

各種標準庫函式的作用是將位元組序列從一個儲存區域複製到另一個儲存區域。當源和目標區域重疊時,大多數這些函式都具有未定義的行為。

例如,這……

#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() 具有明確定義的行為。

區別反映了效率。一般性權衡。諸如這些函式之類的複製通常發生在不相交的儲存區域之間,並且通常可以在開發時知道儲存器複製的特定例項是否屬於該類別。假設非重疊提供了相對更有效的實現,當假設不成立時,這些實現不能可靠地產生正確的結果。大多數 C 庫函式都允許更有效的實現,memmove() 填補空白,為源和目標可能或重疊的情況提供服務。然而,為了在所有情況下產生正確的效果,它必須執行額外的測試和/或採用相對低效的實現。