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

C語言字串拼接函數 strcat() 完全指南:原型、參數、返回值與實戰陷阱

     編輯:關於C語言

C語言字串拼接函數 strcat() 完全指南:原型、參數、返回值與實戰陷阱

strcat() 是 <string.h> 中用於字串尾部追加的核心函數。雖然用法看似簡單,但其「目標緩衝區必須足夠大」「不檢查邊界」「源目不可重疊」等特性,使其成為緩衝區溢出漏洞的高發區。本文系統梳理原型、行為、返回值、標準用法與安全替代方案。

一、 函數原型與標準說明

#include <string.h>

char *strcat(char *dest, const char *src);
項目說明
dest目標字串指標,必須指向一個**足夠大、可寫、以 '\0' 結尾**的字元陣列。原有結尾 '\0' 會被覆蓋。
src源字串指標,內容將被追加到 dest 末尾,src 本身不變。
返回值返回 dest(起始地址),便於鏈式調用,如 strcat(strcat(buf, "A"), "B")。
核心行為1. 定位 dest 末尾 '\0'
2. 從 src 複製字元覆蓋該 '\0' 及後續位置
3. 複製 src 的 '\0' 作為新結尾

二、 標準用法示例

#include <stdio.h>
#include <string.h>

int main(void) {
    char str[80] = {0}; // 足夠大的緩衝區,初始化為 0 確保首個 '\0'
    
    strcpy(str, "here ");
    strcat(str, "is ");
    strcat(str, "the ");
    strcat(str, "xiaoz ");
    
    puts(str); // 輸出: here is the xiaoz
    return 0;
}

三、 核心陷阱與避坑指南

1. 緩衝區溢出 —— 最危險的隱患

char dest[10] = "hello"; // 只有 10 字節
strcat(dest, " world!"); // 需 12 字節(含 '\0')-> 溢出!破壞棧內存,導致崩潰或安全漏洞

防範: 永遠確保 strlen(dest) + strlen(src) + 1 <= sizeof(dest)。

2. 目標未初始化或無結尾符

char dest[20]; // 未初始化,棧上隨機值
strcat(dest, "test"); // 從隨機位置找 '\0',行為未定義

防範: 定義時初始化 char dest[20] = {0}; 或先 strcpy(dest, "");。

3. 源目記憶體重疊

char buf[20] = "hello";
strcat(buf, buf + 2); // src 指向 buf 內部 -> 未定義行為

標準規定: dest 與 src 所指記憶體區域**不得重疊**。需重疊操作請用 memmove。

4. 修改字串常量崩潰

char *p = "hello";
strcat(p, " world"); // p 指向唯讀段 -> 段錯誤

防範: 目標必須是可寫陣列 char arr[] = "hello";。

四、 安全替代方案:strncat 與 strlcat

函數原型特性可用性
strncatchar *strncat(char *dest, const char *src, size_t n)最多追加 n 字元,**不保證**結果以 '\0' 結尾(若 src 長度 >= n)C89 標準,廣泛可用
strlcatsize_t strlcat(char *dest, const char *src, size_t dstsize)**保證**結果以 '\0' 結尾,返回嘗試創建的總長度,便於檢測截斷BSD 擴展,Linux 需 #define _GNU_SOURCE,Windows 無

strncat 安全用法模式

char dest[20] = "hello";
size_t remaining = sizeof(dest) - strlen(dest) - 1; // 預留 '\0' 位置
if (remaining > 0) {
    strncat(dest, " world!", remaining);
}

五、 實戰最佳實踐清單

  1. 定義緩衝區時靜態計算最大可能長度,或動態分配(malloc(strlen(a)+strlen(b)+1))。
  2. 優先使用 snprintf 進行格式化拼接:snprintf(buf, sizeof(buf), "%s%s", s1, s2); 更安全、可讀、可控。
  3. 嚴禁在未知長度輸入上使用 strcat(如網絡數據、用戶輸入)。
  4. 代碼審計關鍵字: 搜索 strcat、strcpy、sprintf、gets 等不安全函數。

總結

strcat() 雖是 C 語言標準庫基石,但其「不檢查邊界」的設計反映了早期計算資源受限的歷史背景。現代 C 開發應將其視為**受限使用**函數,優先選擇 snprintf、strlcat 或 C++ std::string,從源頭消除緩衝區溢出風險。

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