关于错误的atoi()的行为,我可以假设什么?

标准C库函数atoi在ISO 9899:2011中记录为:

7.22.1数字转换函数

1 atofatoiatolatoll函数不需要影响错误的整数表达式errno的值。 如果无法表示结果的值,则行为未定义。

7.22.1.2 atoiatolatollfunction

概要

 #include  int atoi(const char *nptr); long int atol(const char *nptr); long long int atoll(const char *nptr); 

描述

2 atoiatolatoll函数分别将nptr的字符串的初始部分转换为intlong intlong long int表示。 除了出错的行为,它们相当于

 atoi: (int)strtol(nptr, (char **)NULL, 10) atol: strtol(nptr, (char **)NULL, 10) atoll: strtoll(nptr, (char **)NULL, 10) 

返回

3 atoiatolatoll函数返回转换后的值。

nptr无法解析为整数时,预期的行为是什么? 似乎存在以下四种观点:

  • 不执行转换,返回零。 这是一些像这样的参考文献给出的文档。
  • 行为类似于strtol除了可能没有设置errno 。 这是从“除错误行为除外”中引出的,作为对第7.22.1节的参考。
  • 行为未指定。 这就是POSIX所说的 :

    呼叫atoi(str)应相当于:

     (int) strtol(str, (char **)NULL, 10) 

    除了错误的处理可能不同。 如果无法表示该值,则行为未定义。

    此外,“ 应用程序使用 ”部分说明:

    atoi()函数由strtol()包含但保留,因为它在现有代码中广泛使用。 如果未知该数字在范围内,则应使用strtol(),因为不需要atoi()来执行任何错误检查。

    请注意,POSIX声称该规范与ISO 9899:1999一致(就我而言,它包含与ISO 9899:2011相同的语言):

    此参考页面上描述的function与ISO C标准一致。 此处描述的要求与ISO C标准之间的任何冲突都是无意的。 此量的POSIX.1-2008符合ISO C标准。

    据我当地的POSIX委员会成员说,这是UNIX的历史行为。

  • 行为未定义。 这种解释的产生是因为§7.22.1.2¶2从未明确说明错误发生了什么。 既未定义也未明确实现定义或未指定的行为未定义。

哪些解释是正确的? 请尝试参考权威文档。

nptr无法解析为整数时,预期的行为是什么?

需要说明的是,这个问题适用于

 // Case 1 value = atoi(""); value = atoi(" "); value = atoi("wxyz"); 

而不是以下内容:

 // Case 2 // NULL does not point to a string value = atoi(NULL); // Convert the initial portion, yet has following junk value = atoi("123xyz"); value = atoi("123 "); 

根据整数的用法,可能/可能不是以下。

 // Case 3 // Can be parsed as an _integer_, yet overflows an `int`. value = atoi("12345678901234567890123456789012345678901234567890"); 

ato*()的“非案例2”行为取决于错误的含义

atoiatolatoll函数分别将nptr的字符串的初始部分转换为intlong intlong long int表示。 除了出错的行为,它们相当于
atoi: (int)strtol(nptr, (char **)NULL, 10)
...
C11dr§7.22.1.22


当然错误包括案例3:“如果正确的值超出可表示值的范围”。 strto*() ,虽然可能不是ato*() ,但在这种情况下确实设置了定义的错误errrno 。 由于ato*()的规范不适用于此错误 ,因此溢出(结果)为UB per

未定义的行为在本国际标准中以“未定义的行为”或“省略行为的任何明确定义”一词另有说明。 C11dr§42


对于情况1, strto*()的行为定义良好,未指定影响errno 。 规范详细说明(§7.22.1.44)并称之为“无转换”,而不是错误 。 因此它可以断言案例1 strto*()行为不是错误 ,而是“无转换”。 因此…

“如果不能进行转换,则返回零.C11dr§7.22.1.48

atoi("")必须返回0。