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

C/C++ memcpy 與 memmove 區別深度解析及手寫實現

     編輯:關於C語言

C/C++ memcpy 與 memmove 區別深度解析及手寫實現

`memcpy` 和 `memmove` 都是內存塊拷貝函數,關鍵區別在於**源與目的內存區域重疊時的行為**。本文通過圖解三種重疊情況、標準庫規範、手寫實現代碼,徹底講透二者區別與底層原理。

核心區別一覽

特性memcpymemmove
重疊行為未定義行為(可能數據損壞)保證正確(如同臨時緩衝區)
性能極快(常優化為向量指令)略慢(需檢查重疊/反向拷貝)
適用場景確知不重疊、性能關鍵路徑可能重疊、通用安全拷貝
標準頭文件`` / ```` / ``

三種內存重疊情況圖解

假設 `src` 源區域,`dst` 目標區域,長度 `n`。

情況 1:完全不重疊

src: [S S S S S]
dst:           [D D D D D]

→ `memcpy`、`memmove` 均正常,順序拷貝即可。

情況 2:dst 在 src 之前(低地址),重疊

src:       [S S S S S]
dst: [D D D D D]

→ **順序拷貝安全**。從低地址向高地址拷貝,`dst` 寫入的數據不會覆蓋 `src` 未讀取的數據。`memcpy`、`memmove` 均可用順序拷貝。

情況 3:src 在 dst 之前(低地址),重疊 —— 危險區

src: [S S S S S]
dst:       [D D D D D]

→ **順序拷貝會破壞數據**。例如拷貝前 2 字節時,`dst[0]`、`dst[1]` 覆蓋了 `src[2]`、`src[3]`,導致後續讀取到已被修改的數據。
**解決方案**:**逆向拷貝**(從高地址向低地址)。`memmove` 內部檢測此情況並自動逆向拷貝;`memcpy` 不保證,屬 UB。

手寫實現:memcpy(順序拷貝)

void* my_memcpy(void* dest, const void* src, size_t count) {
    // 斷言檢查空指針(調試用)
    assert(dest != NULL && src != NULL);

    char* d = (char*)dest;
    const char* s = (const char*)src;

    // 字節級順序拷貝
    while (count--) {
        *d++ = *s++;
    }
    return dest; // 返回目的地址,支持鏈式調用
}

手寫實現:memmove(智能選擇方向)

void* my_memmove(void* dest, const void* src, size_t count) {
    assert(dest != NULL && src != NULL);

    char* d = (char*)dest;
    const char* s = (const char*)src;

    if (s < d) {
        // 情況3:src 在 dst 前,重疊風險 → 逆向拷貝
        d += count - 1;
        s += count - 1;
        while (count--) {
            *d-- = *s--;
        }
    } else {
        // 情況1、2:不重疊或 dst 在 src 前 → 順序拷貝
        while (count--) {
            *d++ = *s++;
        }
    }
    return dest;
}

關鍵實現細節

  • 字節級操作:強轉為 `char*`,確保每次移動 1 字節,處理任意類型內存。
  • 指針比較:`s < d` 判斷源在目的前(地址數值小),需逆向拷貝。
  • 邊界情況:`s == d` 時無需拷貝,代碼中 `else` 分支順序拷貝 0 次(`count` 為 0 或循環不進入),正確。
  • 返回值:返回 `dest`,符合標準庫約定,支持 `memmove(a, b, n), memset(...)` 鏈式調用。

標準庫實現優化(補充)

現代 libc(glibc、MSVC CRT 等)對 `memcpy`/`memmove` 高度優化:

  • 對齊檢測:按字長(8/16/32/64 字節)向量化拷貝(SSE/AVX/NEON)。
  • `memmove` 內部仍含重疊檢測邏輯,必要時回退到字節級逆向拷貝。
  • 極小塊(< 16 字節)可能直接展開為指令序列。

最佳實踐建議

  1. **默認用 `memmove`** —— 安全、通用、性能損耗可忽略(除非極熱路徑)。
  2. **確知不重疊且追求極致性能** → `memcpy`(如網絡包組裝、协议解析)。
  3. **結構體賦值**優於 `memcpy`:`dst = src` 由編譯器優化,類型安全。
  4. **C++ 偏好 `std::copy` / `std::copy_backward`** —— 迭代器抽象、類型安全、支持重載。

總結

`memcpy` 假設不重疊,單向拷貝極快;`memmove` 檢測重疊,智能選擇方向,保證語義正確。理解「地址大小關係決定拷貝方向」是掌握內存拷貝本質的關鍵。手寫實現僅 20 行,卻蘊含指針算術、內存模型、UB 避免等核心 C 語言功力。

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