stoi转换16进制字符串必须显式指定base=16且去除"0x"前缀,否则会失败或截断;推荐用stoul/stoull处理大数,stringstream配合std::hex更安全鲁棒。

stoi 转换 16 进制字符串必须显式指定 base
std::stoi 默认按十进制解析,直接传入 "0xFF" 或 "FF" 会失败或截断。必须传入第三个参数 16,且输入字符串**不能带 "0x" 前缀**(否则从第一个非数字字符起截断,"0xFF" 只取到 "0" 得 0)。
常见错误现象:stoi("0xFF") 报 std::invalid_argument;stoi("FF") 不报错但结果为 0(因默认 base=10,F 非十进制数字)。
- 正确写法:
stoi("FF", nullptr, 16)→ 255 - 带前缀需先去掉:
auto s = "0xFF"; if (s.substr(0, 2) == "0x") s = s.substr(2); stoi(s, nullptr, 16) - 若不确定前缀是否存在,用
std::stoul+std::hex流更鲁棒(见下节)
用 stringstream + hex 处理带 0x 前缀的字符串更安全
当输入可能含 "0x"、"0X" 前缀,或需统一处理多种进制时,std::stringstream 配合 std::hex 是更自然的选择。它自动跳过前导空白和 0x,且支持完整整数范围(避免 stoi 的 int 溢出问题)。
使用场景:解析配置文件中的内存地址、颜色值(如 "#AABBCC")、协议字段等含前缀的十六进制数据。
立即学习“C++免费学习笔记(深入)”;
std::string s = "0xFF"; unsigned int val; std::stringstream ss(s); ss >> std::hex >> val; // val == 255 // 若 s = "0x100000000",用 unsigned long long + stoull 更稳妥
stoul / stoull 比 stoi 更适合十六进制大数
十六进制字符串常表示地址、哈希、掩码等大数值,stoi 返回 int(通常 32 位),容易溢出。应优先用 std::stoul(unsigned long)或 std::stoull(unsigned long long),它们同样支持 base=16 参数。
性能与兼容性影响:所有 stox 系列函数底层调用 strtol/strtoul,开销接近;但 stoull 在 32 位平台仍可安全解析 64 位十六进制值(如 "FFFFFFFFFFFFFFFF")。
-
stoul("FFFFFFFF", nullptr, 16)→ 4294967295(32 位全 1) -
stoull("10000000000000000", nullptr, 16)→ 18446744073709551616(16^16) - 错误处理:检查异常或用
end指针判断是否全部转换成功
注意 locale 和空格导致的静默失败
默认 std::stoi 和 std::stoul 使用 C locale,但若程序中修改过全局 locale(如调用 std::setlocale(LC_ALL, "")),可能导致十六进制字母 a-f 解析失败(某些 locale 把 a 当作数字)。同时,这些函数**不跳过首尾空格**——" FF " 会直接抛 invalid_argument。
- 安全做法:手动 trim 字符串,例如
s.erase(0, s.find_first_not_of(" \t\n\r")); s.erase(s.find_last_not_of(" \t\n\r") + 1); - 避免 locale 干扰:用
std::stringstream时可显式 imbuestd::locale::classic() - 调试技巧:打印
s.data()和s.size(),确认无不可见字符(如 BOM、\r、\0)
0x 就会让整个包解析失败。











