std::stoi可直接转换十六进制字符串,传0自动识别"0x"前缀,传16则强制十六进制;需注意非法字符抛invalid_argument、溢出抛out_of_range;stringstream更鲁棒,支持空格跳过与混合格式,但需检查eof()确保完整解析;raw bytes应memcpy而非stoi;编译期常量直接用0x前缀。

用 std::stoi 直接转字符串形式的十六进制
如果十六进制数以字符串形式存在(比如 "1A"、"0xFF"),std::stoi 是最简方式,它支持自动识别前缀或手动指定进制:
注意:必须传入 0 作为基数参数才能启用前缀识别("0x" 或 "0X" 自动按 16 进制解析);若明确知道是十六进制且无前缀,直接传 16。
std::string s = "1A"; int n = std::stoi(s, nullptr, 16); // → 26 s = "0xFF"; n = std::stoi(s, nullptr, 0); // → 255,0 表示“根据前缀自动推断”
常见坑:
-
std::stoi遇到非法字符(如"1G")会抛std::invalid_argument,不加 try-catch 容易崩溃 - 超出
int范围(如"FFFFFFFF")会抛std::out_of_range,大数建议用std::stoll+long long - 空字符串或只含空白符也会触发异常
用 std::stringstream 处理带前缀或格式混合的输入
当输入可能混杂空格、前缀、甚至其他进制标识时,std::stringstream 更鲁棒,还能复用流对象做多次解析:
std::string s = " 0x1a "; std::stringstream ss(s); ss >> std::hex >> n; // 自动跳过空白,识别 0x 前缀 // n == 26
关键点:
-
std::hex只影响后续整数读取,不改变字符串本身 - 如果字符串里有非十六进制字符(如
"0xFFG"),读取会在'G'处停止,n得到255,但ss.fail()为false—— 必须检查ss.eof()或ss.peek() == EOF才能确认完整解析 - 想重用同一个
std::stringstream解析多个值?记得调用ss.clear()清除错误标志
处理字节序列(raw bytes)而非字符串时别用 stoi
如果手头是内存里的二进制数据(比如 unsigned char buf[4] = {0xFF, 0x00, 0x00, 0x00}),这不是“十六进制字符串转换”,而是**字节序解释问题**。此时:
- 不能调
std::stoi,它只认字符,不认识 raw bytes - 需明确目标类型和端序:例如把小端 4 字节解释为
uint32_t,直接 memcpy:uint32_t val; std::memcpy(&val, buf, sizeof(val)); // 小端机器上 buf={0xFF,0,0,0} → val==255 - 跨平台时避免依赖本机端序,改用
std::byteswap或htole32/be32toh等函数标准化
编译期常量转换:用 0x 前缀写死即可
如果只是想在代码里写一个十六进制常量,让编译器直接当十进制数用(比如数组大小、枚举值),根本不用运行时转换:
constexpr int size = 0x100; // 编译期就是 256,和写 256 完全等价
enum { FLAG_READ = 0x1, FLAG_WRITE = 0x2 };
这种写法零开销、无异常风险,但仅适用于字面量。一旦来源是用户输入、文件读取或网络接收,就必须走运行时解析路径。
真正容易被忽略的是:十六进制字符串解析失败时的错误处理粒度 —— 是直接 abort,还是记录日志后跳过,还是返回默认值并标记失败?这取决于上下文,但 C++ 标准库不会替你决定。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











