std::stoi解析十六进制需显式指定进制16,自动识别"0x"/"0x"前缀但不支持"x"/"x";非法字符抛invalid_argument,溢出抛out_of_range;空格仅允许前导;大数值应改用std::stoul/stoull;高容错需求可用stringstream或手动解析。

std::stoi 用法与常见错误
直接用 std::stoi 转十六进制字符串最简单,但必须显式指定进制,否则默认按十进制解析,"0xFF" 会报错或得到意外结果。
- 必须传入第三个参数
16,例如:std::stoi("FF", nullptr, 16) - 前缀
"0x"或"0X"可选,std::stoi能自动识别,但不支持单独的"x"或大写"X"前缀(如"xFF"会失败) - 遇到非法字符(如空格、字母超出
0-9A-Fa-f)会抛std::invalid_argument;超出int范围则抛std::out_of_range - 如果字符串含前导空格,
std::stoi会跳过;但中间或末尾有空格会导致截断(只解析到第一个空格为止)
std::stoul / std::stoull 处理大数值
十六进制字符串常表示地址或标志位,很容易超过 int 范围(比如 "FFFFFFFF" 在 32 位系统上已溢出),这时必须换用无符号长整型函数。
- 用
std::stoul解析 32 位无符号整数,std::stoull解析 64 位 —— 它们同样需要传16作为进制参数 - 注意:
std::stoul("FFFFFFFF")在 32 位平台返回4294967295,而std::stoi("FFFFFFFF")会抛std::out_of_range - 如果不确定输入长度,优先用
std::stoull配合uint64_t,避免隐式截断
手动解析:绕过异常、控制容错逻辑
当需要忽略前导/后缀非十六进制字符、跳过空白、或自定义错误码而非抛异常时,std::stoi 就不够用了。
- 用
std::stringstream配合std::hex流操纵器更灵活:std::stringstream ss("0xFF"); unsigned int x; ss >> std::hex >> x; -
ss.fail()判断是否解析失败,比捕获异常轻量;ss.peek()可检查是否还有未读字符,用于验证“完全匹配” - 若需逐字符解析(比如处理带下划线的格式
"0xFF_AB"),得自己遍历字符串,用std::isdigit(c) || (std::tolower(c) >= 'a' && std::tolower(c) 校验,再用 <code>(c >= '0' && c 转值
跨平台兼容性与编码陷阱
Windows 下某些旧编译器(如 MSVC 2013)对宽字符十六进制字符串支持不一致,std::stoul(L"FF", nullptr, 16) 可能失败;Linux GCC 和现代 MSVC(2015+)基本没问题。
- 统一用窄字符串(
std::string)最稳妥,避免std::wstring带来的编码歧义 - 不要依赖 locale 设置 ——
std::stoi默认使用 C locale,改 locale 可能导致a-f不被识别 - 如果输入来自文件或网络,确认源数据是 UTF-8 编码且不含 BOM;BOM(如
EF BB BF)会被当作非法首字符导致解析失败
实际用的时候,先看输入格式是否规整:规整就用 std::stoull(str, nullptr, 16);需要容错或校验完整性,就上 std::stringstream;真要处理畸形输入或嵌入式环境无 STL,才手写解析。别忘了检查返回值或异常,尤其在生产代码里。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











