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

C語言字符串拷貝函數深度對比:strcpy vs strncpy vs memcpy 避坑指南

     編輯:關於C

函數原型


#include 
char *strcpy(char *dest, const char *src);
char *strncpy(char *dest, const char *src, size_t n);
void *memcpy(void *dest, const void *src, size_t n);

核心區別對比表

特性strcpystrncpymemcpy
停止條件遇到 \0複製 n 字符或遇 \0固定複製 n 字節
補 \0自動補齊若 src 長度 ≥ n,**不補 \0**從不處理 \0
適用場景字符串整體複製固定長度緩衝區、防溢出二進制數據、含 \0 的內存塊
返回值destdestdest
重疊安全不安全不安全不安全(用 memmove)

三大經典坑點實測

坑 1:strcpy 緩衝區溢出


char src[] = "123456789";      // 10 字節含 \0
char dest[8];                  // 僅 8 字節
strcpy(dest, src);             // 💥 踩內存!寫入 10 字節

後果:覆蓋相鄰變量、破壞棧幀、返回地址被改寫 → 隨機崩潰/安全漏洞。

坑 2:strncpy 不補 \0 導致字符串非法


char src[] = "123456789";
char dest[8] = {0};
strncpy(dest, src, 9);  // n = src 長度(含\0)
// 結果:dest = "12345678" **無結束符**!
printf("%s", dest);     // 💥 讀越界直到遇到隨機 \0

修正:n = sizeof(dest) - 1,並手動補 \0:


strncpy(dest, src, sizeof(dest) - 1);
dest[sizeof(dest) - 1] = '\0';  // 保證結束

坑 3:memcpy 複製字符串遇嵌入 \0 截斷


char src[] = "ab\0cd";  // 含嵌入 \0
char dest[10];
memcpy(dest, src, sizeof(src));  // 完整複製 6 字節
// dest 內容:'a','b','\0','c','d','\0' — 正確保留嵌入 \0
// 但若用 strcpy/strncpy 會在第一個 \0 停止!

結論:處理二進制數據/結構體/含 \0 內存必須用 memcpy。

安全替代方案

函數標準特點
strlcpyBSD / C23保證 \0 結束,返回 src 長度
strcpy_sC11 Annex K檢查緩衝區大小,失敗返回錯誤碼
memmoveC89處理重疊內存區域

// 手寫安全版 strcpy(教學用)
char *safe_strcpy(char *dest, size_t dest_size, const char *src) {
    if (dest_size == 0) return NULL;
    size_t i = 0;
    for (; i < dest_size - 1 && src[i]; i++)
        dest[i] = src[i];
    dest[i] = '\0';
    return dest;
}

選擇決策樹

  1. 複製純字符串,目標緩衝區足夠大 → strcpy(或更安全的 strlcpy)
  2. 複製字符串,目標緩衝區**固定大小** → strncpy + 手動補 \0,或 strlcpy
  3. 複製二進制數據/結構體/含 \0 內存塊 → memcpy(或重疊用 memmove)
  4. 需要類型安全/編譯期檢查 → C++ std::string/std::vector/std::span

編譯器檢測輔助

  • -Wstringop-overflow (GCC 8+):靜態分析檢測已知大小緩衝區溢出
  • -D_FORTIFY_SOURCE=2:運行時檢查 strcpy/strncpy 等
  • AddressSanitizer:-fsanitize=address 精準捕獲越界寫入

總結

strcpy 簡單但危險,strncpy 設計缺陷(不保證 \0),memcpy 通用但需手動管理長度。**現代 C 開發首選 strlcpy/memcpy 組合,配合編譯器硬化選項**,並在代碼規範中禁止裸用 strcpy/strncpy。理解「字符串以 \0 結束」與「內存塊按字節計數」的本質區別,是避免內存錯誤的關鍵。

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