strtoull 总是 return 一个有效数字或设置 errno 吗?
Does strtoull always return a valid number or set errno?
是否保证 strtoull
为 return 一个有效数字,或设置 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
:
If the correct value is outside the range of representable values, LONG_MIN
, LONG_MAX
, LLONG_MIN
, LLONG_MAX
, ULONG_MAX
, or ULLONG_MAX
is returned (according to the return type and sign of the value, if any), and the value of the macro ERANGE
is stored in errno
.
但是,还有另一种可能的错误情况。 “如果无法执行转换,则返回零,”并且“nptr
的值存储在 endptr
指向的对象中,前提是 endptr
不是空指针。 ”否则,指向“最终字符串”的指针将存储在那里,这将比 nptr
.
更大
因此,真正符合标准的 C 程序应该检查这两个条件。这个测试程序,在 Windows 10:
上用 clang -std=c18
编译
#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;
}
产生输出 a1: No error
,因此在此实现中,未设置 errno
。
正如 chqrlie 在评论中提到的那样,检查 ( errno || s == unparsed )
就足够了。如果这些条件都不成立,则对非空主题序列执行了转换。
是否保证 strtoull
为 return 一个有效数字,或设置 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
:
If the correct value is outside the range of representable values,
LONG_MIN
,LONG_MAX
,LLONG_MIN
,LLONG_MAX
,ULONG_MAX
, orULLONG_MAX
is returned (according to the return type and sign of the value, if any), and the value of the macroERANGE
is stored inerrno
.
但是,还有另一种可能的错误情况。 “如果无法执行转换,则返回零,”并且“nptr
的值存储在 endptr
指向的对象中,前提是 endptr
不是空指针。 ”否则,指向“最终字符串”的指针将存储在那里,这将比 nptr
.
因此,真正符合标准的 C 程序应该检查这两个条件。这个测试程序,在 Windows 10:
上用clang -std=c18
编译
#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;
}
产生输出 a1: No error
,因此在此实现中,未设置 errno
。
正如 chqrlie 在评论中提到的那样,检查 ( errno || s == unparsed )
就足够了。如果这些条件都不成立,则对非空主题序列执行了转换。