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

C 語言手寫 strcpy:不使用庫函數實現字串複製

     編輯:關於C

標準 strcpy 行為

char* strcpy(char* dest, const char* src);
// 複製 src 至 dest,包含結束符 '\0'
// 返回 dest 原始值
// 行為未定義:dest 空間不足、src/dest 重疊、src 非以 \0 結尾

手寫實作 (教學版)

char* my_strcpy(char* dest, const char* src) {
    // 1. 參數驗證
    if (dest == NULL || src == NULL) return NULL;
    
    // 2. 保存 dest 起始位址 (返回值)
    char* ret = dest;
    
    // 3. 核心複製迴圈:複製字元並檢查結束符
    // 先賦值再判斷,確保 '\0' 也被複製
    while ((*dest++ = *src++) != '\0') {
        // 本體為空,所有工作在條件表達式完成
    }
    
    // 4. 返回原始 dest
    return ret;
}

逐行邏輯解析

  1. if (dest==NULL || src==NULL):防禦性程式設計,避免空指標解引用崩潰
  2. char* ret = dest:儲存起始位址,因 `dest` 會在迴圈中遞增
  3. while ((*dest++ = *src++) != '\0'):經典單行複製
    • `*src++`:取得 src 當前字元,src 遞增
    • `*dest++ = ...`:寫入 dest 當前位置,dest 遞增
    • `!= '\0'`:檢查剛寫入的字元是否為結束符
    • 若為 `\0`:複製完成,迴圈結束,`\0` 已寫入 dest
  4. return ret:返回原始 dest,符合標準庫慣例,支援鏈式呼叫

完整測試程式

#include 

char* my_strcpy(char* dest, const char* src) {
    if (!dest || !src) return NULL;
    char* ret = dest;
    while ((*dest++ = *src++) != '\0');
    return ret;
}

int main() {
    char src[] = "Hello, World!";
    char dest[50];
    
    printf("複製前: dest = \"%s\"\n", dest);
    my_strcpy(dest, src);
    printf("複製後: dest = \"%s\"\n", dest);
    printf("返回值指向: %s\n", my_strcpy(dest, "New String"));
    
    // 測試空字串
    char empty[] = "";
    my_strcpy(dest, empty);
    printf("空字串複製: '%s' (長度 %zu)\n", dest, strlen(dest));
    
    return 0;
}

關鍵變體:strncpy (長度限制)

char* my_strncpy(char* dest, const char* src, size_t n) {
    if (!dest || !src) return NULL;
    char* ret = dest;
    while (n-- && (*dest++ = *src++) != '\0');
    // 若 src 結束而 n>0,需補 \0 (標準 strncpy 行為)
    while (n--) *dest++ = '\0';
    return ret;
}

常見錯誤與陷阱

錯誤寫法問題修正
while (*src) *dest++ = *src++;未複製結束符 '\0'改為 do-while 或條件包含賦值
char* dest = "literal"; strcpy(dest, src);字串常數不可修改用陣列 `char dest[100]` 或 malloc
未檢查 dest 空間大小緩衝區溢位使用 strncpy 或確保足夠大
src 與 dest 重疊行為未定義用 memmove 或保證不重疊
返回 dest 而非原始值破壞鏈式呼叫慣例保存並返回起始位址

效能優化版 (位元組對齊複製)

// 針對長字串,按 word (4/8 bytes) 複製
char* fast_strcpy(char* dest, const char* src) {
    char* ret = dest;
    // 對齊到 word 邊界
    while ((uintptr_t)dest % sizeof(long) && (*dest++ = *src++));
    // 批量複製
    long* d = (long*)dest;
    const long* s = (const long*)src;
    while (!has_zero_byte(*s)) *d++ = *s++;
    // 剩餘位元組
    dest = (char*)d; src = (char*)s;
    while ((*dest++ = *src++) != '\0');
    return ret;
}

// 檢測 64-bit word 中是否包含 0 byte
int has_zero_byte(unsigned long x) {
    return (x - 0x0101010101010101UL) & ~x & 0x8080808080808080UL;
}

標準庫實作參考 (glibc)

  • 使用汇編最佳化 (SSE2/AVX/NEON)
  • 向量化載入/儲存 16/32 位元組
  • 無分支結束檢測 (位元運算)
  • 對齊處理:頭尾不對齊用位元組,中間向量化

手寫 strcpy 是理解指標運算、字串結構、函數介面設計的基礎訓練。掌握單行複製慣用語 `while (*d++ = *s++)` 是 C 程式設計師的必修課。

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