标准库函数可高效完成进制转换:std::stoi/stol支持2–36进制解析,需注意base合法性及异常;std::to_string仅支持十进制,转其他进制需用std::stringstream、std::bitset或C++20的std::format。

直接用标准库函数就能完成大部分进制转换,不需要手写除基取余——但前提是搞清输入输出类型和边界条件。
用 std::stoi 和 std::stol 解析任意进制字符串
这两个函数支持把字符串按指定进制转成整数,base 参数范围是 2–36。常见错误是传错 base 或忽略异常:
-
std::stoi("1010", nullptr, 2)→ 返回10(不是字符串"10") -
std::stoi("FF", nullptr, 16)→ 返回255 -
std::stoi("87", nullptr, 8)会抛出std::invalid_argument,因为'8'不是合法八进制数字 - 如果字符串含空格或前导零,
std::stoi默认跳过前导空白,但不会自动处理"0x"前缀——除非你传0作为base,此时它才按 C 风格识别0(八进制)、0x(十六进制)
用 std::to_string 只能转十进制,换其他进制得靠 std::stringstream 或 std::format(C++20)
std::to_string 固定输出十进制,要转二、八、十六进制必须换方法:
- C++11 起推荐用
std::stringstream配合std::hex/std::oct/std::bitset - C++20 可用
std::format("{:x}", 255)直接生成小写十六进制字符串 - 转二进制最稳妥是
std::bitset,但需编译时知道位宽;例如std::bitset(10).to_string()→"00001010"
std::stringstream ss;
ss << std::hex << 255; // 小写十六进制
std::string hex_str = ss.str(); // "ff"
ss.str(""); ss.clear();
ss << std::uppercase << std::hex << 255; // 大写
hex_str = ss.str(); // "FF"
注意符号与无符号整数的转换差异
负数用 std::stoi 解析带符号进制串没问题(如 "-101" 二进制),但反过来用 std::bitset 或 std::stringstream 输出时,默认不带符号位——它只表示数值绝对值的二进制形式。真要输出补码,得先转成对应宽度的无符号类型再处理:
立即学习“C++免费学习笔记(深入)”;
-
std::bitset(static_cast→(-1)) "11111111"(正确补码) - 直接
std::bitset(-1)会触发隐式转换警告,且结果依赖实现 - 八进制和十六进制输出不体现符号,全靠上下文理解是否为有符号值
避免用 itoa ——它不是标准 C++ 函数
很多旧代码里出现的 itoa 是 GCC/MSVC 扩展,跨平台编译会失败。替代方案明确:
- 需要格式化控制(如固定宽度、补零)→ 用
std::stringstream+std::setfill+std::setw - 只求简洁转换且用 C++20 →
std::format最安全 - 性能敏感且进制固定 → 手写查表法(如 0–15 → '0'–'9','A'–'F')比流操作快,但可读性下降
std::stringstream ss;
ss << std::hex << std::setw(4) << std::setfill('0') << 255;
std::string padded = ss.str(); // "00ff"
真正容易出问题的地方不在算法,而在对输入合法性判断和目标类型宽度的预估——比如把一个 32 位十六进制字符串喂给 std::stoi,可能溢出;或者用 std::bitset 存不下 20 位二进制数。这些边界得靠调用方自己守,标准库不会替你截断或扩展。











