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

C 語言內存操作函數族全解析:memcpy、memmove、memcmp、memchr、memset、memccpy

     編輯:關於C語言

內存操作函數是 C 語言標準庫 `` 的核心組成,直接操作字節序列,不關心類型,是系統編程、嵌入式開發、高性能計算的基石。本文系統梳理六大函數的原型、語義差異、重疊行為、返回值與避坑指南。

函數速查總表

函數功能重疊處理返回值典型用途
memcpy內存拷貝未定義行為 (UB)dest非重疊區域高速拷貝
memmove內存移動安全處理 (內部用臨時緩衝或逆向拷貝)dest可能重疊區域 (數組插入/刪除)
memcmp內存比較只讀,無重疍問題<0 / =0 / >0二進制數據比較、排序
memchr查找字節只讀指針 / NULL原始緩衝區查找特定字節
memset內存設置只寫dest清零結構體、初始化緩衝區
memccpy拷貝至指定字節UB (同 memcpy)下一字節指針 / NULL解析以特定字節結尾的協議數據

核心函數深度解析

1. memcpy vs memmove:重疊是分水嶺

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

關鍵差異:

  • memcpy:假設 dest 與 src 不重疊,編譯器可優化為向量指令 (SSE/AVX/NEON),極快。重疊時行為未定義 (數據損壞、崩潰、看似正常)
  • memmove:內部檢測重疊方向,選擇正向/逆向拷貝,保證語義正確,微小性能開銷

決策規則: 不確定是否重疊 → 用 memmove;確定不重疊 → 用 memcpy。現代 libc 中 `memcpy` 內部常檢測重疍自動降級為 `memmove`,但標準不保證。

2. memcmp:二進制比較的基石

int memcmp(const void *s1, const void *s2, size_t n);
  • 按 無符號字節 逐個比較 (相當於 `unsigned char`)
  • 返回首個不同字節的差值:`*(uchar*)s1 - *(uchar*)s2`
  • 用於:結構體比較 (需無填充洞)、二進制排序、校驗和驗證
  • 陷阱:包含填充字節的結構體直接 `memcmp` 結果不可靠

3. memchr:查找單字節

void *memchr(const void *s, int c, size_t n);
  • 在前 n 字節中查找字節 c (轉為 `unsigned char`)
  • 返回首次出現地址,未找到返回 NULL
  • 配合指針運算可實現簡易分割器:`memchr(buf, '\n', len)`

4. memset:清零/初始化利器

void *memset(void *s, int c, size_t n);
  • 將前 n 字節設置為字節值 c (低 8 位有效)
  • 只能設置字節模式:`memset(arr, 0, sizeof(arr))` 清零正確;`memset(arr, 1, ...)` 將每字節置 1 (非整數 1);不可用於設置非 0/-1 的整數數組
  • 編譯器常優化為向量存儲指令

5. memccpy:遇字節停止拷貝 (BSD/GNU 擴展,非 C 標準)

void *memccpy(void *dest, const void *src, int c, size_t n);
  • 拷貝至遇到字節 c (含該字節) 或完成 n 字節
  • 返回 dest 中 c 後的下一字節指針;未遇到返回 NULL
  • 適用:解析以換行符/空字節結尾的可變長度協議字段
  • 注意:非標準 C,跨平台需自帶實現或用 `memchr`+`memcpy` 組合

memicmp:忽略大小寫比較 (Microsoft/BSD 擴展)

int memicmp(const void *s1, const void *s2, size_t n);
  • 逐字節比較,字母不區分大小寫 (依賴當前 locale)
  • 非標準,跨平台請用 `strncasecmp` (POSIX) 或手寫循環

實戰避坑指南

場景錯誤做法正確做法
結構體拷貝`memcpy(&dst, &src, sizeof(dst))` 可能重疊`memmove` 或直接賦值 `dst = src`
結構體比較`memcmp(&a, &b, sizeof(a)) == 0`逐字段比較,或 `memset(&a, 0, sizeof(a))` 後再比
整數數組清零`memset(arr, 0, sizeof(arr))` ✓正確 (全位 0 即整數 0)
整數數組置 1`memset(arr, 1, sizeof(arr))` ✗循環賦值 或 `std::fill`
指針數組清零`memset(ptr_arr, 0, sizeof(ptr_arr))` ✓正確 (全位 0 即空指針)
float/double 清零`memset(arr, 0, sizeof(arr))` ✓正確 (IEEE 754 全位 0 即 0.0)
重疊緩衝區移動`memcpy(buf+2, buf, 10)` ✗`memmove(buf+2, buf, 10)` ✓

現代 C++ 替代方案

C 函數C++ 替代優勢
memcpy`std::copy`, `std::copy_n`類型安全、支援迭代器、重疍安全
memmove`std::move` (算法), `std::copy_backward`同上
memcmp`std::equal`, `std::lexicographical_compare`泛型、可自定義比較
memchr`std::find`類型安全
memset`std::fill`, `std::fill_n`類型安全、非字節模式也可

總結

內存操作函數族是「字節級編程」的基石。**`memmove` 安全通吃,`memcpy` 極速專用,`memcmp` 二進制比較,`memchr` 查找,`memset` 清零初始化**。理解「重疊語義」、「字節模式限制」、「無符號比較」三大核心概念,能寫出正確、高效、可移植的系統級代碼。C++ 專案優先使用 `` 算法替代,獲得類型安全與泛型能力。

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