<string.h> 提供兩大族函數:mem* 面向內存塊(不因 \0 停止,需指定字節數 size_t n),str* 面向字符串(遇 \0 停止)。strn* 兼具二者:遇 \0 或達 n 字節停止,相對安全。本文按功能分組深度解析。
| 函數 | 原型 | 語義 | 關鍵點 |
|---|---|---|---|
memcpy | void *memcpy(void *dest, const void *src, size_t n) | 內存拷貝 n 字節 | 不檢查重疊,src 與 dest 重疊行為未定義 |
memmove | void *memmove(void *dest, const void *src, size_t n) | 安全內存拷貝 | 正確處理重疊(內部用臨時緩衝或反向拷貝) |
strcpy | char *strcpy(char *dest, const char *src) | 字符串拷貝含 \0 | 無長度限制,**極易溢出** |
strncpy | char *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, ","); }
| 危險函數 | 風險 | 推薦替代 |
|---|---|---|
strcpy/strcat | 緩衝區溢出 | strncpy/strncat + 手動補 \0,或 snprintf |
sprintf | 格式化溢出 | snprintf |
gets | 無長度限制 | fgets |
strtok | 非線程安全、修改原串 | strtok_r / 手寫解析器 |