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

memcpy 與 memmove 差異深度解析:記憶體重疊處理機制

     編輯:關於C++

memcpy 與 memmove 皆用於記憶體區塊複製,關鍵差異在於**記憶體區塊重疊時的行為**。本文透過原始碼分析,釐清兩者適用場景與效能考量。

函數原型

void *memcpy(void *dest, const void *src, size_t n);
void *memmove(void *dest, const void *src, size_t n);

核心差異:重疊處理

memcpy:不處理重疊,行為未定義

void *memcpy(void *dest, const void *src, size_t n) {
    char *d = (char*)dest;
    const char *s = (const char*)src;
    while (n--) *d++ = *s++;  // 單向正向複製
    return dest;
}

若 src 區塊位於 dest 區塊之前且重疊,正向複製會覆寫尚未讀取的來源資料,導致資料損毀。

memmove:安全處理重疊,雙向複製策略

void *memmove(void *dest, const void *src, size_t n) {
    char *d = (char*)dest;
    const char *s = (const char*)src;

    if (d <= s || d >= s + n) {
        // 情況 1:無重疊 或 dest 在 src 之前(不重疊區域)
        // 正向複製安全
        while (n--) *d++ = *s++;
    } else {
        // 情況 2:dest 在 src 之後且重疊
        // 必須反向複製,避免覆寫來源
        d += n - 1;
        s += n - 1;
        while (n--) *d-- = *s--;
    }
    return dest;
}

記憶體重疊判斷條件

兩區塊 不重疊 條件:

dest <= src  ||  dest >= src + n

反之則重疊,必須使用 memmove。

效能比較

場景memcpymemmove
無重疊最快(單純正向複製,編譯器常優化為 SIMD 指令)略慢(需執行重疊判斷分支)
重疊(dest < src)**錯誤結果**正確(正向複製)
重疊(dest > src)**錯誤結果**正確(反向複製)

實務選擇指南

  1. 確定不重疊:使用 memcpy(效能最佳,編譯器積極優化)。
  2. 不確定或可能重疊:使用 memmove(安全正確)。
  3. 結構體複製:優先使用賦值運算子 dst = src 或 std::copy(型別安全、編譯器優化)。
  4. C++ 容器操作:使用 std::copy、std::move、vector::assign 等演算法,避免裸指標操作。

標準庫實作備註

  • 現代 libc(glibc、musl、MSVC CRT)的 memcpy 以高度優化的組合語言實作(AVX2、NEON、SSE2),大塊複製效能極高。
  • memmove 通常在判斷重疊後,同樣呼叫優化的複製核心。
  • C++17 std::memcpy、std::memmove 位於 <cstring>。

測試驗證程式碼

#include <cstring>
#include <iostream>

int main() {
    char buf[20] = "ABCDEFGHIJ";
    std::cout << "原始: " << buf << '\n';

    // 重疊複製:將前 5 字元複製到位置 3 起始
    // 預期結果: "ABCABCDEFG" (memmove) vs 損毀 (memcpy)
    std::memmove(buf + 3, buf, 5);
    std::cout << "memmove: " << buf << '\n';

    std::strcpy(buf, "ABCDEFGHIJ");
    std::memcpy(buf + 3, buf, 5);  // 未定義行為
    std::cout << "memcpy:  " << buf << " (結果不可預期)" << '\n';
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved