Search code examples
cerror-handlinglanguage-lawyerstrtoull

Does strtoull always return a valid number or set errno?


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?


Solution

  • 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, 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.

    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.