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

C標準庫 核心函數分類詳解:mem/str 系列、字符串操作、內存操作與安全陷阱

     編輯:關於C語言

C標準庫 <string.h> 核心函數分類詳解:mem/str 系列、字符串操作、內存操作與安全陷阱

<string.h> 提供兩大族函數:mem* 面向內存塊(不因 \0 停止,需指定字節數 size_t n),str* 面向字符串(遇 \0 停止)。strn* 兼具二者:遇 \0 或達 n 字節停止,相對安全。本文按功能分組深度解析。

一、拷貝函數

函數原型語義關鍵點
memcpyvoid *memcpy(void *dest, const void *src, size_t n)內存拷貝 n 字節不檢查重疊,src 與 dest 重疊行為未定義
memmovevoid *memmove(void *dest, const void *src, size_t n)安全內存拷貝正確處理重疊(內部用臨時緩衝或反向拷貝)
strcpychar *strcpy(char *dest, const char *src)字符串拷貝含 \0無長度限制,**極易溢出**
strncpychar *strncpy(char *dest, const char *src, size_t n)最多拷貝 n 字符若 src 長度 < n,補 \0;若 ≥ n,**不加 \0**,需手動補

最佳實踐:

// 安全拷貝字符串到固定緩衝區
strncpy(dest, src, sizeof(dest)-1);
dest[sizeof(dest)-1] = '\0';

// 結構體內存清零
memset(&st, 0, sizeof(st));

二、比較函數

函數比較對象停止條件
strcmp兩個以 \0 結尾的字符串遇 \0 或字符不同
strncmp至多 n 字符的字符串遇 \0、字符不同、或達 n
memcmp兩個 n 字節的二進制塊達 n 字節或字節不同

返回值: s1返回正值。memcmp 逐字節比較,適合結構體/二進制數據精確比對。

三、查找函數

  • void *memchr(const void *s, int c, size_t n):內存區前 n 字節中找字符 c,返回首個匹配地址或 NULL。
  • char *strchr(const char *s, int c):字符串中找首個 c。
  • char *strrchr(const char *s, int c):字符串中找最後一個 c。

注意: 參數 c 是 int 但只取低 8 位作為字符。

四、memset —— 內存填充

void *memset(void *s, int c, size_t n);
  • 將 s 起始 n 字節設置為字符 c (低 8 位)。
  • **核心用途:結構體/數組清零初始化** memset(&obj, 0, sizeof(obj))。
  • 返回 s。

五、strstr —— 子串查找

char *strstr(const char *haystack, const char *needle);
  • 在 haystack 中找 needle 首次出現位置,返回指針或 NULL。
  • 不包含 needle 的 \0。

六、長度計算

  • size_t strlen(const char *s):計算至 \0 的字符數(不含 \0)。無長度保護,非法字符串導致越界。
  • size_t strnlen(const char *s, size_t maxlen):最多檢查 maxlen 字符,安全版本。

七、拼接函數

  • char *strcat(char *dest, const char *src):src 拼到 dest 末尾,**無緩衝區檢查,極危險**
  • 。
  • char *strncat(char *dest, const char *src, size_t n):最多拼 n 字符,相對安全。**仍需確保 dest 有足夠空間**。

安全拼接模式:

strncat(dest, src, sizeof(dest) - 1 - strlen(dest));

八、strtok —— 字符串分割(狀態機,非線程安全)

char *strtok(char *str, const char *delim);
  • 首次調用傳 str,後續調用傳 NULL,內部靜態指針記錄位置。
  • 修改原字符串(將分隔符替換為 \0)。
  • 線程安全版:strtok_r (POSIX) / strtok_s (C11 Annex K)。
char s[] = "a,b,c"; char *p = strtok(s, ",");
while(p) { puts(p); p = strtok(NULL, ","); }

九、安全陷阱總結與現代替代

C11 Annex K (Bounds-checking interfaces) 提供 strcpy_s, strcat_s, strncpy_s, strtok_s 等帶緩衝區尺寸參數的安全版本,MSVC/新版 GCC/Clang 支持,建議新項目啟用 __STDC_WANT_LIB_EXT1__ 使用。

總結

掌握 mem* (二進制塊、指定長度) 與 str* (字符串、\0 終止) 的語義邊界,永遠優先使用帶長度限制的 n 版本,結構體清零用 memset,字符串拼接用 snprintf,分割用 strtok_r。現代 C 開發應拥抱 snprintf、strnlen、Annex K 安全函數,徹底杜絕緩衝區溢出漏洞。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
危險函數風險推薦替代
strcpy/strcat緩衝區溢出strncpy/strncat + 手動補 \0,或 snprintf
sprintf格式化溢出snprintf
gets無長度限制fgets
strtok非線程安全、修改原串strtok_r / 手寫解析器