首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C 語言字串複製函數遺漏結束符導致亂碼的根因與修正

     編輯:程式設計綜合問答

問題現象

兩版 mcopy 函數複製字串,第一版輸出亂碼,第二版在迴圈結束後手動加上 `t[d] = '\0';` 即正常。為何會產生亂碼?

程式碼對比

版本一(有缺陷)

void mcopy(char *s, char *t, int m) {
    int len = strlen(s);
    for (int i = m-1, d = 0; i < len; i++, d++) {
        t[d] = s[i];
    }
    // 缺少結束符
}

版本二(正確)

void mcopy(char *s, char *t, int m) {
    int len = strlen(s);
    for (int i = m-1, d = 0; i < len; i++, d++) {
        t[d] = s[i];
    }
    t[d] = '\0'; // 關鍵補全
}

根本原因分析

  1. strlen(s) 回傳字串長度 不包含 結束符 `\0`。
  2. 迴圈僅複製有效字元,目的陣列 `t` 原有內容未清零,殘留資料位於新字串末尾之後。
  3. puts(t) 遇不到 `\0` 會繼續讀取記憶體直到隨機遇到 0,導致輸出亂碼。

記憶體圖示

來源 s:  'H' 'e' 'l' 'l' 'o' '\0'
目的 t (複製前):  'X' 'X' 'X' 'X' 'X' 'X' 'X' ...

版本一複製後 t:  'H' 'e' 'l' 'l' 'o' 'X' 'X' ...  ← 無結束符
版本二複製後 t:  'H' 'e' 'l' 'l' 'o' '\0' 'X' ... ← 正確結束

修正最佳實踐

  • 字串操作函數 必須確保以 `\0` 結尾。
  • 使用標準庫 strncpy、snprintf 等自動處理結束符的函數。
  • 若手動實作,複製迴圈結束後顯式寫入 `dest[dest_len] = '\0';`。
  • 開啟編譯器警告(`-Wall -Wextra`),靜態分析工具可偵測此類缺陷。

擴充:安全的字串複製函數範例

void safe_mcopy(const char *src, char *dst, size_t dst_size, int start_idx) {
    if (!src || !dst || dst_size == 0) return;
    size_t src_len = strlen(src);
    if (start_idx < 0 || (size_t)start_idx >= src_len) { dst[0] = '\0'; return; }
    size_t copy_len = src_len - start_idx;
    if (copy_len >= dst_size) copy_len = dst_size - 1; // 留空間給 \0
    memcpy(dst, src + start_idx, copy_len);
    dst[copy_len] = '\0';
}

掌握「C 字串以 `\0` 結尾」這一核心規則,即可避免 90% 的字串處理亂碼問題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved