面試高頻考點:手寫 strcpy、memcpy。看似簡單,實則包含空指針檢查、自拷貝處理、內存重疊安全拷貝、const 正確性、返回值約定等工業級細節。本文給出健壯、標準庫級的實現,並對比兩者核心差異。
char* my_strcpy(char* dest, const char* src) {
// 1. 參數合法性
if (!dest || !src) return NULL; // 或 assert
// 2. 自拷貝直接返回
if (dest == src) return dest;
// 3. 計算長度(含 '\0')
size_t len = strlen(src) + 1;
// 4. 判斷重疊並選擇拷貝方向
// dest 在 src 之前,或 dest 在 src+len 之後:無重疊或安全區域,前向拷貝
// 否則:重疊且 dest 在 src 之後,必須後向拷貝避免覆蓋未讀數據
if (dest < src || dest >= src + len) {
// 前向拷貝
char* d = dest;
const char* s = src;
while (len--) *d++ = *s++;
} else {
// 後向拷貝
char* d = dest + len - 1;
const char* s = src + len - 1;
while (len--) *d-- = *s--;
}
return dest;
}
void* my_memcpy(void* dest, const void* src, size_t n) {
if (!dest || !src) return NULL;
if (dest == src) return dest;
char* d = (char*)dest;
const char* s = (const char*)src;
// 重疊判斷邏輯同 strcpy
if (d < s || d >= s + n) {
// 前向
while (n--) *d++ = *s++;
} else {
// 後向
d += n - 1;
s += n - 1;
while (n--) *d-- = *s--;
}
return dest;
}
| 維度 | strcpy | memcpy |
|---|---|---|
| 拷貝內容 | 僅字符串(以 '\0' 結束) | 任意二進制數據(結構體、數組、整數等) |
| 長度確定 | 遇到 '\0' 停止,隱式長度 | 顯式指定 n 字節 |
| 安全性 | 易溢出,不推薦,用 strncpy/strlcpy | 長度可控,相對安全 |
| 返回值 | 返回 dest | 返回 dest |
| 適用場景 | 字符串複製 | 內存塊移動、結構體賦值、網絡包組裝 |
// strcpy 極簡版(無重疊保護,無空檢查)
char* strcpy_simple(char* dest, const char* src) {
char* ret = dest;
while ((*dest++ = *src++));
return ret;
}
// memcpy 極簡版
void* memcpy_simple(void* dest, const void* src, size_t n) {
char* d = dest;
const char* s = src;
while (n--) *d++ = *s++;
return dest;
}
// strcat: 追加 src 到 dest 末尾
char* my_strcat(char* dest, const char* src) {
char* d = dest;
while (*d) ++d; // 找到 '\0'
while ((*d++ = *src++)); // 拷貝含 '\0'
return dest;
}
// strcmp: 字典序比較
int my_strcmp(const char* s1, const char* s2) {
while (*s1 && *s1 == *s2) { ++s1; ++s2; }
return (unsigned char)*s1 - (unsigned char)*s2;
}
// strlen: 計算長度
size_t my_strlen(const char* s) {
const char* p = s;
while (*p) ++p;
return p - s;
}
// strlwr: 轉小寫(非標準,Windows 有)
char* my_strlwr(char* s) {
for (char* p = s; *p; ++p) *p = tolower(*p);
return s;
}
src 必須 const,防止誤修改源數據。memmove 標準庫函數保證處理重疊,memcpy 標準不保證(實現多為前向),手寫時建議加重疊保護。printf("%s", strcpy(buf, "hello"));。strcmp 中轉 unsigned char 防止負字符值比較錯誤。熟練掌握這些底層內存操作的邊界條件與實現細節,不僅能應付面試,更能在系統編程、嵌入式開發、庫開發中寫出零成本、高可靠的代碼。