4

strtoull保证返回一个有效的数字,或者设置errno(如果没有有效的数字可以被解析)?

换句话说,这是

errno = 0;
n = strtoull(s, 0, 10);
if (errno) {
  perror(s);
  exit(1);
}
// do something with n

正确,还是还需要进行其他检查?

4

1 回答 1

5

没有。C 标准(至少草案 N1570 到 N2454 的第 7.22.1.7 节,所以 C11 到 C18)只errno在一个地方提到了设置:

如果正确的值在可表示值的范围之外,LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX, ULONG_MAX, 或者ULLONG_MAX被返回(根据返回类型和值的符号,如果有的话),宏的值ERANGE存储在errno.

但是,还有另一种可能的错误情况。“如果不能执行转换,则返回零”和“如果不是空指针,则 的值nptr存储在 指向的对象中。” 否则,指向“最终字符串”的指针将被存储在那里,与.endptrendptrnptr

因此,真正符合标准的 C 程序应该检查这两个条件。此测试程序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;
}

产生输出a1: No error,所以在这个实现中,errno没有设置。

正如 chqrlie 在评论中提到的那样,检查( errno || s == unparsed ). 如果这些条件都不成立,则对非空主题序列执行了转换。

于 2021-02-15T23:02:27.310 回答