strtoull是否总是返回有效数字或设置errno?
是否strtoull保证返回有效数字或设置errno(如果无法解析有效数字)?
换句话说,这是
errno = 0;
n = strtoull(s, 0, 10);
if (errno) {
perror(s);
exit(1);
}
// do something with n
正确,还是还需要其他一些检查?
回答
否。 C 标准(至少 N1570 至 N2454 草案的第 7.22.1.7 节,因此 C11 至 C18)仅errno在一处提及设置:
如果正确的值在可表示值的范围之外,则返回
LONG_MIN、LONG_MAX、LLONG_MIN、LLONG_MAX、ULONG_MAX、 或ULLONG_MAX(根据值的返回类型和符号,如果有),宏的值ERANGE存储在errno.
但是,还有另一种可能的错误情况。“如果无法执行转换,则返回零”,并且“ 的值nptr存储在 指向的对象中endptr,前提endptr是该对象不是空指针。” 否则,指向“最终字符串”的指针将存储在那里,它会比nptr.
因此,真正符合标准的 C 程序应该检查这两个条件。这个测试程序,clang -std=c18在 Windows 10 上编译:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
int main (void) {
const char s[] = "a1";
errno = 0;
char* unparsed = NULL;
const unsigned long long int n =
strtoull( s, &unparsed, 10 );
if ( errno || (!n && s == unparsed) ) {
fflush(stdout); // Don't cross the streams!
perror(s);
exit(EXIT_FAILURE);
}
printf( "%llun", n );
return EXIT_SUCCESS;
}
产生 output a1: No error,所以在这个实现中,errno没有设置。
正如 chqrlie 在评论中提到的那样,检查( errno || s == unparsed ). 如果这两个条件都不成立,则对非空主题序列执行了转换。
- Checking the value of `n` seems redundant. If a number was found, `unparsed` will be `> s` to it suffices to write: `if ( errno || s == unparsed )`