std::stoll是c++11引入的字符串转long long函数,用于安全转换十进制等进制整数字符串,自动跳过前导空白、识别正负号,非法输入抛std::invalid_argument或std::out_of_range异常,需try/catch捕获,支持base参数(默认10,0可自动识别0x/0前缀),不返回解析位置,不适合混合格式字符串。

std::stoll 是最直接的转换函数
当字符串内容确定为合法十进制整数(如 "1234567890123"),且不关心错误处理细节时,std::stoll 是首选。它定义在 <string></string> 头文件中,会自动跳过开头空白,识别正负号,并在遇到非法字符时抛出 std::invalid_argument 或 std::out_of_range 异常。
常见错误现象:std::stoll("") 或 std::stoll("abc") 直接崩溃(未捕获异常);std::stoll("9223372036854775808")(超 LLONG_MAX)触发 std::out_of_range。
- 必须用
try/catch包裹,否则程序终止 - 支持自定义进制(第二个参数
base),默认为 10;设为 0 可按前缀自动识别("0x"→16,"0"→8) - 不返回解析长度,无法知道“读到了哪里”,不适合混合格式字符串(如
"123px")
std::strtoll 更适合需要控制解析过程的场景
std::strtoll 来自 <cstdlib></cstdlib>,行为更底层:它接受 char*、返回 long long,并通过输出参数 char** endptr 告诉你解析停在哪。这让你能判断是否整个字符串都被成功解析,或提取前缀数字后继续处理剩余部分。
使用场景举例:解析带单位的尺寸字符串 "1024px",或校验用户输入是否“纯数字”。
- 传入
nullptr给endptr会失去位置信息,等同于放弃控制权 - 返回值在溢出时是
LLONG_MAX或LLONG_MIN,且errno被设为ERANGE—— 必须同时检查errno和返回值 - 空字符串或全空白时返回 0,但
*endptr指向首字符,可据此区分“0”和“无效”
注意 locale 和负号的隐式依赖
std::stoll 和 std::strtoll 都受当前 C locale 影响,但仅限千位分隔符(如 '\'')——而标准 C++ 解析器默认**不识别任何千位分隔符**。真正容易被忽略的是负号:它们只认 ASCII '-'(U+002D),不接受全角减号、en dash(–)或 em dash(—)。若用户输入来自网页表单或富文本编辑器,可能混入这些 Unicode 字符,导致解析失败。
- 不要假设输入“看起来像数字”就一定可转:先用
std::all_of过滤或预清洗非 ASCII 符号 - 若需支持 locale 特定格式(如德语逗号作小数点),必须自己实现解析逻辑,标准函数不适用
- Windows 上某些 CRT 实现对宽字符支持有限,若用
std::wstring,应改用_wcstoll或std::stoll的宽字符重载(C++11 起支持)
安全边界:为什么不能只靠异常或 errno
即使加了 try/catch 或检查 errno,仍可能漏掉两类问题:一是输入含不可见控制字符(如 "\t-123" 被接受,但业务上可能不允许前导空白);二是数值虽在 long long 范围内,却超出下游接口要求(如数据库 BIGINT SIGNED 限制,或协议要求非负)。
- 业务层必须定义“有效范围”,例如用
if (val MAX_ID)二次校验 - 对用户输入,建议先用
std::regex或std::span<const char></const>扫描确认格式合规,再调用转换函数 - 性能敏感路径(如日志解析)可考虑
absl::SimpleAtoi(需引入 Abseil)或手写无异常分支的 ASCII 数字解析,避免异常开销
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











