c++中如何将16进制字符串转换为整数_c++ stoi与hex用法【实例】

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_argumentstoi("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,且支持完整整数范围(避免 stoiint 溢出问题)。

使用场景:解析配置文件中的内存地址、颜色值(如 "#AABBCC")、协议字段等含前缀的十六进制数据。

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::stoulunsigned long)或 std::stoullunsigned 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::stoistd::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 时可显式 imbue std::locale::classic()
  • 调试技巧:打印 s.data()s.size(),确认无不可见字符(如 BOM、\r、\0)
十六进制字符串转换看着简单,真正上线时出问题的几乎全是前缀处理、空格、locale 和整数宽度这四点。尤其嵌入式或协议解析场景,一个没 trim 的空格或一个没处理的 0x 就会让整个包解析失败。