stoul("ff")会出错是因为默认按十进制解析,遇到非数字字符'f'立即抛出std::invalid_argument异常;C++标准库不支持隐式进制推断,必须显式指定base=16。

直接用 std::stoul 就能转,但必须显式指定进制为 16,否则默认按十进制解析,"ff" 会报错或结果错误。
为什么 stoul("ff") 会出错?
std::stoul 默认按十进制(base = 10)解析字符串。遇到非数字字符(如 'f')立即抛出 std::invalid_argument 异常。它不会自动识别 "0xff" 这类前缀格式——C++ 标准库不支持隐式进制推断。
常见错误现象:
-
stoul("ff")→ 抛出std::invalid_argument -
stoul("0xff")→ 同样失败,因为'0'和'x'在十进制下非法 -
stoul("ff", nullptr, 16)→ 正确,显式指定base = 16
stoul 的三个参数怎么配?
函数原型是:unsigned long stoul(const string& str, size_t* pos = nullptr, int base = 10)。关键在第三参数 base,十六进制必须传 16;第二参数可选,用于获取解析结束位置。
立即学习“C++免费学习笔记(深入)”;
实操建议:
- 总是显式传
16,别依赖默认值 - 用
size_t idx捕获解析偏移,验证是否整个字符串都被消费:if (idx != str.length())表示有无效后缀 - 注意返回类型是
unsigned long,超范围会抛std::out_of_range
std::string s = "1a3f";
size_t idx;
try {
unsigned long val = std::stoul(s, &idx, 16);
if (idx == s.length()) {
// 解析完整,val == 6719
}
} catch (const std::exception& e) {
// 处理 invalid_argument 或 out_of_range
}和 std::stoi、std::stoull 有什么区别?
核心差异在返回类型和取值范围,不是功能逻辑:
-
std::stoi→ 返回int,通常 32 位,最大约2^31-1;"ffffffff"在多数平台会溢出 -
std::stoul→ 返回unsigned long,Windows 下常为 32 位,Linux/macOS 通常 64 位;需查sizeof(unsigned long) -
std::stoull→ 返回unsigned long long,保证至少 64 位,适合长十六进制串(如哈希值)
性能和兼容性影响:三者底层解析逻辑一致,无显著性能差;但跨平台时 unsigned long 位宽不统一,处理超过 4 字节的十六进制串应优先选 stoull。
要不要自己写解析?
绝大多数场景不需要。标准库 stoul 已高度优化,且正确处理前导空格、符号(十六进制不支持负号)、溢出异常。唯一例外是:你需要容忍非法字符后缀(如 "ffabc" 只取前两位),此时可手动遍历 + std::isdigit/std::isxdigit,但要自行管理进制转换和溢出检查。
容易被忽略的点:十六进制字符串不区分大小写("FF" 和 "ff" 都合法),stoul 原生支持;但如果你手写循环,记得用 std::tolower 或直接比较大小写字符。











