C 标准库整数解析函数的设计缺陷与安全用法

C 标准库整数解析函数的设计缺陷与安全用法

_

C 标准库里没有安全的整数解析函数,这不是一个新发现,但它的实际影响往往被低估。主流的解析方法有三种:atol()、strtol()/strtoul() 以及 sscanf(),但它们各自存在严重的设计缺陷,在处理不可信输入时可能导致难以预料的结果。

atol(): 完全无法使用

atol() 的问题最为直接:它没有任何错误返回值。当输入 "123timmy" 时,它返回 123;当输入超大数值时返回 LONG_MAX;当输入空字符串或纯空格时返回 0。调用者完全没有办法知道发生了什么。更糟的是,C 标准规定如果值无法被表示,行为是未定义的这意味着 atol() 理论上甚至可以擦除你的硬盘。虽然在实际中不会出现这么极端的情况,但你无法依赖这一点——对不可信输入使用 atol(),本质上是在获取一个随机值。

strtol(): 可以正确使用

strtol() 其实能够实现安全解析,关键在于正确的调用方式。解析前需要将 errno 设为 0,解析后检查 errno 是否被设置为 ERANGE,同时还要检查 endp 指针是否指向了字符串末尾。如果 endp 不为空,说明解析没有处理完整输入。这两个条件都必须检查,缺一不可。具体实现代码并不复杂,但必须严格遵循这个模式,否则仍然不能保证正确性。好消息是,对于有符号整数,strtol() 确实可以做到可靠解析。

strtoul(): 设计缺陷导致无用

strtoul() 的问题在于它对“负数加无符号”的处理方式。以输入 “-1”为例,它不会报错,而是返回一个巨大的无符号数值(2^64-1)。输入 “-9223372036854775808”(即 -2^63)时,返回 2^63。这种转换在技术上没有错,但它完全不是大多数程序员期望的行为。该函数的本意是将被解析字符串转换为无符号长整型,但结果往往与用户想要的数值相差甚远,可以说是一个从根本上就有问题的设计。

sscanf(): 同样不可靠

也许有人会认为 sscanf() 能解决问题,但实际上它也有自己的问题。从测试结果看,当输入超出范围时,sscanf() 并不会停止解析,后续行为变得不可预测。它无法一致性地处理所有边界情况,同样不适合用于解析不可信输入。

结论

在 C 语言中处理整数解析时,唯一真正可靠的方法是使用 strtol() 并严格检查 errno 和 endp 两个条件。其它所有方法都存在这样或那样的问题,在生产环境中都不应该用来解析来自用户的输入。如果对可靠性有更高要求,可能需要考虑使用第三方库,或者等待 C++ 的 std::from_chars() 这样的更安全的替代方案普及。

编注:信源为个人技术博客,作者为 C/Unix 领域开发者。材料详细分析了几种整数解析方法的缺陷与局限,供有一定 C 编程基础的读者参考。


寒武纪股价超越茅台重归A股第二高价,市值距九千亿一步之遥 2026-05-20
Firefox 148 禁用 asm.js 优化:OdinMonkey 迎来黄昏 2026-05-20