【发布时间】:2016-11-18 11:45:34
【问题描述】:
标准 C 库函数 atoi 在 ISO 9899:2011 中记录为:
7.22.1 数值转换函数
1 函数
atof、atoi、atol和atoll在出错时不需要影响整数表达式errno的值。如果结果的值无法表示,则行为未定义。...
7.22.1.2
atoi、atol和atoll函数概要
#include <stdlib.h> int atoi(const char *nptr); long int atol(const char *nptr); long long int atoll(const char *nptr);说明
2
atoi、atol和atoll函数将nptr指向的字符串的初始部分分别转换为int、long int和long long int表示。除了错误的行为,它们等价于atoi: (int)strtol(nptr, (char **)NULL, 10) atol: strtol(nptr, (char **)NULL, 10) atoll: strtoll(nptr, (char **)NULL, 10)返回
3
atoi、atol和atoll函数返回转换后的值。
当nptr 指向的字符串不能被解析为整数时,预期的行为是什么?似乎存在以下四种观点:
-
不执行任何转换并返回零。这是 this one 等一些参考文献给出的文档。
-
行为类似于
strtol,只是errno可能没有设置。这源于将“错误行为除外”作为对 §7.22.1 ¶1 的引用。 -
行为未指定。这就是POSIX says:
调用 atoi(str) 应相当于:
(int) strtol(str, (char **)NULL, 10)除了错误的处理可能不同。如果值无法表示,则行为未定义。
此外,应用程序使用部分指出:
atoi() 函数被 strtol() 包含,但由于它在现有代码中广泛使用而被保留。如果不知道该数字在范围内,则应使用 strtol(),因为 atoi() 不需要执行任何错误检查。
请注意,POSIX 声称该规范符合 ISO 9899:1999(就我而言,它包含与 ISO 9899:2011 相同的语言):
此参考页面上描述的功能符合 ISO C 标准。此处描述的要求与 ISO C 标准之间的任何冲突都是无意的。本卷 POSIX.1-2008 遵循 ISO C 标准。
据我当地的 POSIX 委员会成员说,这是 UNIX 的历史行为。
-
行为未定义。之所以出现这种解释,是因为 §7.22.1.2 ¶2 从未明确说明错误会发生什么。既没有定义也没有明确实现定义或未指定的行为是未定义的。
这些解释中哪一个是正确的?请尽量参考权威文档。
【问题讨论】:
-
If the value of the result cannot be represented, the behavior is undefined. -
@cpplearner 当您尝试解析的数字超出结果类型的范围时,这句话适用。它不适用于输入根本无法解析的情况,此后不存在任何值。
-
如果“错误行为”包括没有数字要转换时发生的情况,那么它是未定义的。如果这不是“错误”,则返回值为 0。但如果知道精确的行为如此重要,为什么不直接使用文档更完善的函数
strtol代替呢? (或者如果您希望返回类型为int而不是long int,则将strtol包装在您自己的函数中?) -
@DavidK 因为我想知道答案。
标签: c language-lawyer undefined-behavior atoi