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

时间:2016-07-15 09:55:16

标签: c language-lawyer undefined-behavior atoi

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

  

7.22.1数字转换函数

     

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

     

...

     

7.22.1.2 atoiatolatoll函数

     

概要

#include <stdlib.h>
int atoi(const char *nptr);
long int atol(const char *nptr);
long long int atoll(const char *nptr);
     

描述

     

2 atoiatolatoll函数将nptr指向的字符串的初始部分转换为int,{{1}分别表示{和} long int。除了出错的行为外,它们等同于

long long int
     

返回

     

3 atoi: (int)strtol(nptr, (char **)NULL, 10) atol: strtol(nptr, (char **)NULL, 10) atoll: strtoll(nptr, (char **)NULL, 10) atoiatol函数返回转换后的值。

atoll指向的字符串无法解析为整数时的预期行为是什么?似乎存在以下四种观点:

  • 不执行转换,返回零。这是一些参考文献给出的文档,如this one
  • 行为与nptr的行为类似,但可能未设置strtol。这是从“除错误行为除外”中引出的,作为对§7.22.1¶1的参考。
  • 行为未指定。这就是POSIX says

      

    呼叫atoi(str)应相当于:

    errno
         

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

    此外,应用程序用法部分指出:

      

    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从未明确说明错误发生了什么。既未定义也未明确实现已定义或未指定的行为未定义。

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

1 个答案:

答案 0 :(得分:2)

  

// 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*()

atoi的“非案例2”行为取决于

错误的含义
  

atolatollnptr函数将int指向的字符串的初始部分转换为long intlong long intatoi: (int)strtol(nptr, (char **)NULL, 10)表示。除错误上的行为外,它们相当于
      ...
      strto*()
  C11dr§7.22.1.22

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

  

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

对于案例1,errno的行为已明确定义,未指定影响strto*()。规范详细说明(§7.22.1.44)并将其称为“无转换”,而不是错误。因此它可以断言案例1 atoi("")行为不是错误,而是“无转换”。因此,每...

  

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

... If hWnd Then 'SetForegroundWindow (hWnd) 'changing the folder name 'Sleep 200 SendKeys "{BACKSPACE}" Sleep 200 For x = 1 To Len(Sample) lngPM = PostMessage(hWnd, WM_SETTEXT, Asc(Mid(Sample, x, 1)), 1&) Sleep 200 Next x Sleep 200 SendMessageByString hWnd, WM_SETTEXT, Len(Sample), Sample End If Application.Wait (Now + TimeValue("00:0:03")) 必须返回0。