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

C語言 memcpy 完全指南:內存拷貝語法、重疊陷阱、類型無關性與實戰模式

     編輯:關於C語言

函數原型與核心語義

#include 
void *memcpy(void *dest, const void *src, size_t n);
  • 功能: 從 src 複製 n **字節** 到 dest。
  • 返回: dest (鏈式調用)。
  • 核心特性:
    1. 類型無關 — 參數為 void*,任意類型 (整型、浮點、結構體、字符、不可見控制字符) 均可拷貝,不依賴 '\0' 結束符。
    2. 按字節拷貝 — 逐字節復制,不關心對齊、類型大小。
    3. 不檢查重疊 — 若 src 和 dest 內存區域重疊,行為未定義 (UB)。重疊場景必須用 memmove。

基本用法示例

1. 字符數組拷貝 (最直觀)

char src[10] = {1,2,3,4,5,6,7,8,9,10};
char dst[10];
memcpy(dst, src, 10); // 複製 10 字節
// dst = {1,2,3,4,5,6,7,8,9,10}

2. 整型數組拷貝 (注意字節數計算)

int src[5] = {1,2,3,4,5};
int dst[10] = {0};
memcpy(dst, src, sizeof(int) * 5); // 必須 * sizeof(int) = 20 字節
// dst = {1,2,3,4,5,0,0,0,0,0}

3. 結構體整體拷貝 (淺拷貝)

struct Point { int x, y; };
struct Point a = {10, 20}, b;
memcpy(&b, &a, sizeof(struct Point)); // 或 sizeof(a)
// b.x=10, b.y=20
// 注意:若結構體含指針,僅拷貝指針值 (淺拷貝),指向同一內存!

4. 部分拷貝 (指定字節數)

int src[10] = {1,2,3,4,5,6,7,8,9,10};
int dst[10];
memcpy(dst, src, sizeof(int) * 3); // 僅複製前 3 個 int (12 字節)
// dst = {1,2,3, 隨機值...}

重疊陷阱 — 必須用 memmove

char buf[20] = "abcdefghijklmnop";
// 將前 10 字節向後移 5 位 (區域重疊)
memcpy(buf + 5, buf, 10); // UB!可能導致數據損壞、崩潰
// 正確:
memmove(buf + 5, buf, 10); // 安全處理重疊,內部判斷方向拷貝
// 結果: "abcdeabcdefghijkl" (前 5 字節不變,後 10 字節覆蓋)

判斷標準: dest 在 src 與 src+n 之間 (或反之) 即為重疊。**不確定就用 memmove**,性能差異微乎其微。

memcpy vs strcpy vs memmove

特性memcpystrcpymemmove
結束條件指定字節數 n遇到 '\0' 停止指定字節數 n
適用數據任意二進制 (含 '\0')僅 C 字符串任意二進制
重疊處理**UB (未定義行為)**UB (通常同向拷貝導致無限循環)**安全 (自動判斷方向)**
性能最快 (編譯器常內聯向量化)需掃描 '\0'略慢於 memcpy (分支判斷)
返回值destdestdest

避坑檢查清單

  1. ❌ **第三參數寫元素個數而非字節數** — memcpy(dst, src, 10) 拷貝 10 字節,若 int[10] 需 10*sizeof(int)。
  2. ❌ **目標緩衝區太小** — memcpy 不檢查邊界,寫入越界 → 緩衝區溢出、崩潰、安全漏洞。**調用方負責確保 dest 容量 ≥ n**。
  3. ❌ **重疊內存用 memcpy** — 任何可能重疊場景 (數組移位、緩衝區壓縮、字符串插入/刪除) **強制用 memmove**。
  4. ❌ **含指針/虛函數表的結構體/C++對象淺拷貝** — 導致雙重釋放、懸空指針、虛函數調用崩潰。需實現深拷貝 (拷貝構造函數/賦值運算符)。
  5. ❌ **用於非連續內存 (如鏈表節點間)** — memcpy 要求連續線性地址空間。
  6. ✅ **大塊內存拷貝首選 memcpy** — 編譯器優化極佳 (SIMD、rep movsb)。
  7. ✅ **結構體賦值 b = a 優於 memcpy** — 編譯器生成優化代碼,C++ 調用拷貝構造/賦值,語義正確。
  8. ✅ **C++ 現代代碼優先用 std::copy/std::copy_n** — 類型安全、支持迭代器、可內聯優化、支持重疊 (隨機訪問迭代器)。

實戰代碼模板

// 1. 安全拷貝封裝 (C)
bool safe_memcpy(void *dest, size_t dest_cap, const void *src, size_t n) {
    if (dest_cap < n) return false; // 容量檢查
    memcpy(dest, src, n);
    return true;
}

// 2. 結構體淺拷貝 (僅 POD)
#define COPY_POD(dst, src) memcpy(&(dst), &(src), sizeof(dst))

// 3. 重疊安全移動
// 數組插入: 向後騰空
memmove(&arr[idx+1], &arr[idx], (len - idx) * sizeof(arr[0]));
arr[idx] = new_val;

// 4. C++ 現代替代
#include 
#include 
std::copy(src, src + n, dest);           // 指針版
std::copy_n(src, n, dest);               // 指定長度
std::vector v(src, src + n);        // 構造容器
// 重疊安全: std::copy_backward (逆向拷貝) 或 std::move (移動語義)

總結

memcpy = 高速、類型無關、按字節、非重疊專用。
牢記:「第三參數是字節數、重疊用 memmove、C++對象別用、目標容量自查」。

掌握 memcpy 的「類型盲拷貝、字節計數、重疊 UB」三大核心特性,配合 memmove 重疊安全、結構體淺拷貝限制、C++ 算法替代,即可在系統編程、協議解析、緩衝區管理中高效、安全地操作原始內存。

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