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 ) 就足够了。如果这些条件都不成立,则对非空主题序列执行了转换。