std::stoi适用于以'\0'结尾的C风格字符串,自动跳过空格、识别符号,但要求输入合法且不超int范围;std::from_chars更底层、无异常、支持进制指定但需手动检查错误码和指针位置;手动转换灵活但需谨慎处理溢出和符号。

用 std::stoi 直接转换 C 风格字符串
只要一维字符数组以 '\0' 结尾(即符合 C 字符串要求),std::stoi 是最直接的选择。它内部会跳过前导空格,识别正负号,并在遇到非数字字符时停止解析。
常见错误是传入未初始化或未以 '\0' 结尾的数组,导致未定义行为——比如读越界或解析出错值。
- 确保数组末尾有
'\0':例如char buf[10] = "123";是安全的;但char buf[3] = {'1','2','3'};不是,缺少终止符 -
std::stoi抛异常:输入为空、全空白、超出int范围时抛std::invalid_argument或std::out_of_range,必须捕获 - 只处理十进制:不支持
0x前缀或0开头的八进制,如"0123"仍按十进制解析为 123
用 std::from_chars 实现无异常、精确控制
这是 C++17 引入的底层转换函数,不抛异常、不依赖 locale、不分配内存,适合性能敏感或需明确错误码的场景。但它要求输入是严格数字序列,不跳过空格,也不识别符号位(除非显式允许)。
典型误用是忽略返回的 ec(error code)或没检查 ptr 是否移动——比如输入 "123abc" 会成功解析 123,但 ptr 指向 'a',若不检查就认为整个字符串有效。
立即学习“C++免费学习笔记(深入)”;
- 必须传入
char*和长度,不能只传指针:例如std::from_chars(buf, buf + len, value) - 支持进制指定:第三个参数可设为
10(默认)、8、16,但不会自动识别0x前缀 - 返回结构体含
ptr(下一个未处理字符)和ec(std::errc::invalid_argument或std::errc::result_out_of_range)
手动遍历转换:控制细节但易出错
当需要自定义规则(比如忽略某些分隔符、支持逗号分隔符、或限制位数)时,手动循环仍是可靠选择,但容易漏掉溢出检查或符号处理。
最常被忽略的是整数溢出——特别是用 int 累加时,value * 10 + digit 可能在乘法后就溢出,而非加法后。应提前判断:if (value > INT_MAX / 10 || (value == INT_MAX / 10 && digit > 7))。
- 先处理符号:记录
sign,统一按正数算,最后再乘 - 逐字符判断
c >= '0' && c ,别用 <code>isdigit(c)(依赖 locale,且对 signed char 可能 UB) - 终止条件要明确:遇到非数字、
'\0'、或达到预设长度就停
别把 atoi 当安全默认选项
atoi 看似简单,但错误处理完全失效:输入非法时返回 0,无法区分 "0" 和 "abc"。而且不检查溢出,超范围时行为未定义(常见是 wrap-around,但标准不保证)。
除非在嵌入式等极简环境且输入绝对可信,否则不建议使用。它和 std::stoi 的接口差异也容易埋坑——atoi 接受 const char*,但不告诉你解析到哪了。
- 没有错误反馈机制:返回值 0 永远是歧义的
- 不支持进制切换:只能十进制
- 不检查缓冲区边界:若传入野指针或无终止符数组,直接崩溃
真正要注意的不是“哪种函数最快”,而是“你能否可靠地知道转换是否发生、在哪停止、为什么失败”。尤其在解析用户输入或协议字段时,std::from_chars 的 ptr 和 ec 比异常更利于定位问题;而 std::stoi 的异常机制更适合上层逻辑快速失败。手动实现则只应在上述两者都无法满足约束时才考虑。


















