| 參數 | 說明 |
nptr | 待轉換字符串指針 |
endptr | 輸出參數,若非 NULL,存儲轉換結束位置的下一字符指針(用於錯誤檢查/繼續解析) |
base | 進制基數:2~36 或 0。0 表示自動檢測:0x 前綴→16進制,0 前綴→8進制,否則 10 進制 |
轉換規則
- 跳過前導空白字符(
isspace)
- 可選符號
+ / -
- 若
base=0 或 base=16,可選 0x/0X 前綴
- 盡可能多地匹配合法數字字符(0-9, a-z/A-Z 對應值 < base)
- 遇非法字符或字符串結束停止
返回值與錯誤處理
- 成功:返回轉換後的
long 值
- 溢出:返回
LONG_MAX 或 LONG_MIN,並設置 errno = ERANGE
- 無合法數字:返回 0,
endptr 指向 nptr
對比:strtol vs atoi vs sscanf
| 特性 | strtol | atoi | sscanf |
| 錯誤檢測 | 完善(endptr + errno) | 無(返回 0 無法區分錯誤) | 一般(返回匹配項數) |
| 進制支持 | 2-36 + 自動檢測 | 僅 10 進制 | 格式字符串控制 |
| 溢出處理 | 飽和 + errno | 未定義行為 | 未定義行為 |
| 性能 | 高 | 高 | 較低(解析格式串) |
| 線程安全 | 是 | 是 | 是 |
最佳實踐代碼模板
long safe_strtol(const char *s, int base, bool *ok) {
char *end;
errno = 0;
long val = strtol(s, &end, base);
if (end == s) { // 無任何數字被消耗
*ok = false; return 0;
}
if (errno == ERANGE) { // 溢出
*ok = false; return val; // val 為 LONG_MAX/MIN
}
if (*end != '\0') { // 尾部有殘留非數字字符(可選嚴格模式)
*ok = false; return val;
}
*ok = true; return val;
}
進階用法:解析多數字字符串
void parse_numbers(const char *s) {
char *end = (char *)s;
while (*end) {
errno = 0;
long val = strtol(end, &end, 10);
if (end == (char *)s) break; // 無進展,防死循環
if (errno == ERANGE) { /* 處理溢出 */ }
printf("解析到: %ld\n", val);
// end 已指向下一個待解析字符,循環繼續
}
}
相關函數族
strtoul / strtoull:無符號長整型 / 64 位
strtod / strtof / strtold:浮點數
strtoimax / strtoumax:C99 最大寬度整數
- 上一篇文章: GCC 編譯器參數完全指南:從入門到交叉編譯
- 下一篇文章: Linux 內核模塊開發:Netfilter 協議棧抓包 + Procfs 輸出實戰
Copyright ©
程式碼之家 All Rights Reserved