手寫 strcpy 與 strlen,考察指標操作、空字元處理、緩衝區安全意識。
// 字串複製:回傳目的地址,支援鏈式呼叫
char *my_strcpy(char *dest, const char *src) {
char *ret = dest;
while ((*dest++ = *src++) != '\0'); // 複製包含結束符
return ret;
}
// 字串長度:不包含結束符
size_t my_strlen(const char *str) {
size_t len = 0;
while (*str++) len++;
return len;
}
const char *src:承諾不修改來源。while (*dest++ = *src++):賦值表達式值為賦值結果,遇 \0 為 0 結束循環,且 \0 已寫入目的地。dest 原始值(ret),符合標準庫行為。strlen 回傳 size_t(無號),避免負長度。// strncpy 風格:限制最大複製字元數,確保以 \0 結尾
char *my_strncpy(char *dest, const char *src, size_t n) {
char *ret = dest;
while (n-- > 0 && (*dest++ = *src++));
if (n == 0) *dest = '\0'; // 來源過長,手動結尾
return ret;
}
// 安全長度:限制最大掃描長度,防無結束符字串導致越界
size_t my_strnlen(const char *str, size_t maxlen) {
size_t len = 0;
while (len < maxlen && *str++) len++;
return len;
}
\0 → 目的字串無結尾,後續操作越界。dest 空間不足 → 緩衝區溢位(需呼叫端保證或用 strncpy)。src 與 dest 重疊 → 行為未定義(應用 memmove)。strlen 用於二進位資料 → 遇 \0 截斷,錯誤。文章提供兩個版本:
char c[10] → 若來源超過 9 字元溢位。char c[strlen(s)] → VLA 長度不含結束符,仍會溢位 1 字元。正確應為 strlen(s)+1。strcpy/strlen(編譯器內建優化)。strlcpy (BSD) 或 strcpy_s (C11 Annex K)。字串操作是 C 語言指標掌握度的試金石,手寫 strcpy/strlen 能快速檢驗候選人對記憶體模型、空字元約定、緩衝區安全的理解深度。