首页 文章

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

提问于
浏览
6

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

7.22.1数字转换函数1 atof,atoi,atol和atoll函数不需要影响错误中整数表达式errno的值 . 如果无法表示结果的值,则行为未定义 . ...... 7.22.1.2 atoi,atol和环礁功能概要#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)
环礁:strtoll(nptr,(char **)NULL,10)
返回3 atoi,atol和atoll函数返回转换后的值 .

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

  • 未执行转换,返回零 . 这是一些参考文献给出的文档,如this one .

  • 行为类似于 strtol ,但可能未设置 errno . 这是从“除错误行为之外”中引出的,作为对第7.22.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从未明确说明错误发生了什么 . 既未定义也未明确实现已定义或未指定的行为未定义 .

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

1 回答

  • 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*() 的"non-Case 2"行为取决于 error in的含义

    atoi,atol和atoll函数分别将nptr指向的字符串的初始部分转换为int,long int和long long int表示 . 除了出错的行为,它们等同于atoi:(int)strtol(nptr,(char **)NULL,10)...C11dr§7.22.1.22


    当然 error 包括案例3:"If the correct value is outside the range of representable values" . strto*() ,虽然可能不是 ato*() ,但在这种情况下确实设置了 <errno.h> 中定义的错误号 errrno . 由于 ato*() 的规范不适用于此 error ,溢出,结果是每个UB

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


    对于案例1, strto*() 的行为已明确定义,未指定影响 errno . 规范详细说明(§7.22.1.44)并调用这些"no conversion",而不是 error . 所以它可以断言案例1 strto*() 行为不是 error ,而是"no conversion" . 因此...

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

    ... atoi("") 必须返回0 .

相关问题