| 函數 | 原型 | 複製單位 | 結束條件 | 重疊處理 | 補 \0 |
|---|---|---|---|---|---|
| strcpy | char* strcpy(char* dest, const char* src) | 字元 | 遇 \0 | 未定義行為 (UB) | 是 |
| strncpy | char* strncpy(char* dest, const char* src, size_t n) | 字元 | n 字元或 \0 | UB | src |
| memcpy | void* memcpy(void* dest, const void* src, size_t n) | 位元組 | n 位元組 | UB | 否 (不關心 \0) |
| memmove | void* memmove(void* dest, const void* src, size_t n) | 位元組 | n 位元組 | **安全支援重疊** | 否 |
char s1[8] = "str-1"; char s2[] = "str-2and123"; // 11 字元 strcpy(s1, s2); // 寫入 11 字元,溢出 s1,污染相鄰變數 s3
**禁用 strcpy**,改用 strncpy 或 snprintf。
strncpy(dest, src, sizeof(dest)-1); dest[sizeof(dest)-1] = '\0'; // 手動保證結尾
char buf[] = "abcdefgh"; memmove(buf+2, buf, 4); // 正確: "ababcdgh" memcpy(buf+2, buf, 4); // UB: 可能 "ababcdgh" 或亂碼
memmove 內部自動判斷方向 (前向/後向複製) 避免覆蓋。
struct Data { int a; double b; };
struct Data src = {1, 2.0}, dest;
memcpy(&dest, &src, sizeof(src)); // 結構體整體複製
// strcpy
char *my_strcpy(char *d, const char *s) {
char *ret = d;
while ((*d++ = *s++));
return ret;
}
// memmove (支援重疊)
void *my_memmove(void *d, const void *s, size_t n) {
char *pd = d; const char *ps = s;
if (pd > ps && pd < ps + n) { // 目的在來源後方且重疊 -> 從後向前複製
pd += n; ps += n;
while (n--) *--pd = *--ps;
} else { // 否則從前向後
while (n--) *pd++ = *ps++;
}
return d;
}