Is strtoull
guaranteed to either return a valid number, or set errno
(if no valid number could be parsed)?
In other words, is this
errno = 0;
n = strtoull(s, 0, 10);
if (errno) {
perror(s);
exit(1);
}
// do something with n
correct, or is some other check also required?
No. The C standard (§7.22.1.7 of at least drafts N1570 through N2454, so C11 through C18) only mentions setting errno
in one place:
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
.
There is another possible error condition, however. “If no conversion could be performed, zero is returned,” and “the value of nptr
is stored in the object pointed to by endptr
, provided that endptr
is not a null pointer.” Otherwise, a pointer to “the final string” would be stored there, which would compare greater to nptr
.
Therefore, a truly standard-compliant C program should check both conditions. This test program, compiled with clang -std=c18
on 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;
}
produces the output a1: No error
, so on this implementation, errno
is not set.
As chqrlie brings up in the comments, it would have sufficed to check ( errno || s == unparsed )
. If neither of these conditions hold, there was a conversion performed on a non-empty subject sequence.