字串/記憶體操作是 C 程式核心技能,標準庫函數隱藏諸多細節 (重疊處理、邊界檢查、錯誤返回)。本文解析四大高頻函數規格、自製實現與最佳實踐。
void *memcpy(void *dest, const void *src, size_t n);
n 字節,**不檢查 '\\0'**,二進制安全。dest 與 src 記憶體區域重疊。dest 支援鏈式呼叫。void *my_memcpy(void *dest, const void *src, size_t n) {
if (!dest || !src) return NULL;
char *d = dest; const char *s = src;
for (size_t i = 0; i < n; i++) d[i] = s[i];
return dest;
}
void *memmove(void *dest, const void *src, size_t n);
memcpy,但**保證重疊時正確** (內部自動判斷方向複製)。memcpy (需檢查/反向複製)。dest < src 正向複製;dest > src 反向複製 (從尾部開始)。int atoi(const char *nptr);
strtol(nptr, NULL, 10)。int my_atoi(const char *str) {
int sign = 1, base = 0, i = 0;
while (str[i] == ' ') i++;
if (str[i] == '-' || str[i] == '+') sign = 1 - 2*(str[i++]=='-');
while (str[i] >= '0' && str[i] <= '9') {
if (base > INT_MAX/10 || (base==INT_MAX/10 && str[i]-'0' > 7))
return sign==1 ? INT_MAX : INT_MIN;
base = 10*base + (str[i++]-'0');
}
return base * sign;
}
char *strstr(const char *haystack, const char *needle);
haystack 中首次出現 needle 的位址,找不到返回 NULL。needle 返回 haystack。char *my_strstr(const char *h, const char *n) {
if (!*n) return (char*)h;
for (size_t i = 0; h[i]; i++) {
size_t j = 0;
while (h[i+j] == n[j]) {
if (!n[++j]) return (char*)(h+i);
}
}
return NULL;
}
| 函數 | 常見錯誤 | 正確做法 |
|---|---|---|
| memcpy | 重疊區域複製 (如 memcpy(buf+2, buf, 10)) | 改用 memmove |
| atoi | 不檢查錯誤,"abc" 返回 0 假以為成功 | 用 strtol/strtoll 檢查 endptr 與 errno |
| strstr | 未檢查 NULL 直接解參考 | if (p) { ... } |
| 所有 | 緩衝區溢出 (目標空間不足) | 確保 dest 容量 ≥ n |