strtoull
是否保证会返回有效的数字,或者在无法解析有效数字时设置errno
?
换句话说,这是否如下所示:
errno = 0;
n = strtoull(s, 0, 10);
if (errno) {
perror(s);
exit(1);
}
// do something with n
是否正确,还是需要其他的检查?
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
中。
然而,还有另外一个可能的错误条件。“如果没有进行转换,则返回零”,“如果endptr
不是空指针,则将nptr
的值存储在endptr
所指向的对象中。”否则,将在那里存储指向“最终字符串”的指针,该指针与nptr
相比较会更大。
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( "%llu\n", n );
return EXIT_SUCCESS;
}
在这个实现中,errno
没有被设置,因此输出为a1: No error
。
正如chqrlie在评论中提到的那样,检查( errno || s == unparsed )
已经足够。如果这两个条件都不成立,则对非空主题序列执行了转换。
n
的值似乎是多余的。如果找到了一个数字,unparsed
将会 > s
,所以只需写:if (errno || s == unparsed)
。 - chqrlie
errno
— 参见C11 §7.22.1.4 Thestrtol
,strtoll
,strtoul
和strtoull
functions。实现时,可能会设置errno
,但根据C标准,这不是强制性的。(在我打字的时候,问题同时被标记为C和C++)。我今天没有检查C++标准是否也是如此。另请参见Correct usage ofstrtol
。根据标准,需要进行更多的检查。 - Jonathan Leffler