首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C 語言字串連接函數 strcat 與 strncat 差異詳解與安全實踐

     編輯:關於C語言

函數原型


char *strcat(char *restrict dest, const char *restrict src);
char *strncat(char *restrict dest, const char *restrict src, size_t n);

核心行為差異

特性strcatstrncat
連接長度src 全長 (含結束符)最多 n 字元 (不含結束符)
結束符處理覆蓋 dest 結束符,複製 src 結束符若 n < src長:複製 n 字元後自動添加結束符
若 n >= src長:行為同 strcat
返回值destdest
緩衝區溢出風險極高 (無長度檢查)可控 (需 dest 空間 ≥ strlen(dest) + n + 1)

底層邏輯圖解


// strcat 等價實現
char *strcat(char *dest, const char *src) {
    char *d = dest;
    while (*d) d++;        // 定位 dest 結束符
    while ((*d++ = *src++)); // 複製 src (含結束符)
    return dest;
}

// strncat 等價實現
char *strncat(char *dest, const char *src, size_t n) {
    char *d = dest;
    while (*d) d++;        // 定位 dest 結束符
    while (n-- && (*d++ = *src++)); // 複製最多 n 字元
    *d = '\0';             // 關鍵:強制添加結束符
    return dest;
}

測試代碼與輸出分析


int main() {
    char a[20] = "Hello";
    char b[] = "World";
    char c[] = "!!!";
    
    printf("Initial: a=[%s]\n", a);        // Hello
    
    strncat(a, b, 3);                      // 連接 "Wor"
    printf("strncat 3: a=[%s]\n", a);      // HelloWor
    
    strncat(a, c, 10);                     // n > 長度,全連接
    printf("strncat 10: a=[%s]\n", a);     // HelloWor!!!
    
    return 0;
}

重疊內存未定義行為警示

所有 str* 函數均不支援源目重疊:


char buf[20] = "ABCDEF";
strcat(buf, buf + 2); // 未定義行為!src 在 dest 內部

需用 memmove 處理重疊區域。

安全替代方案

函數標準特點
strlcatBSD (非標準)接收 dest 總容量,保證不溢出,返回嘗試長度
strcat_sC11 Annex K帶運行時約束檢查,違規調用處理函數
snprintfC99snprintf(dest, size, "%s%s", dest, src) 通用安全

最佳實踐清單

  1. 優先用 snprintf:snprintf(buf, sizeof(buf), "%s%s", prefix, suffix) 一次完成,自動截斷、保證結束符
  2. 若用 strncat 必須計算剩餘空間:strncat(dest, src, sizeof(dest) - strlen(dest) - 1)
  3. 禁用 strcat:代碼審查應標記為缺陷
  4. 輸入驗證:確保 src 非 NULL、以 '\0' 結尾
  5. 靜態分析:啟用 -Wstringop-overflow (GCC/Clang) 捕獲潛在溢出

總結

strcat 是不安全的歷史遺留,strncat 提供長度限制但參數語義易混淆 (n 是追加字元數而非總容量)。現代 C 代碼應統一遷移至 snprintf 或 strlcat,從源頭消除緩衝區溢出隱患。

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