4

strtoull("-1", NULL, 0)在我测试的系统(OS/X 与 Apple Libc,Linux 与 Glibc)上评估为18446744073709551615, (0xFFFFFFFFFFFFFFFF又名ULLONG_MAX)。

既然strtoull应该检查返回类型范围之外的值,为什么它不返回0所有负值?

编辑:周围的行为-ULLONG_MAX似乎也不一致:

strtoul("-18446744073709551615", NULL, 0) -> 1, errno=0
strtoul("-18446744073709551616", NULL, 0) -> 18446744073709551615, errno=34
4

1 回答 1

10

C 节标准(C99 中的第 7.20.1.4 节,C11 中的第 7.22.1.4 节,两者中的第 5 段)的主流解释是在第一步中执行转换,忽略负号,产生无符号结果。然后否定这个结果。这是由

如果主题序列以减号开头,则转换产生的值被否定(在返回类型中)。

在标准文本中。 unsigned 类型的取反值是明确定义的,因此如果第一步产生可表示的值,则整体结果是可表示的。由于否定,没有后续错误。

另一方面,如果输入字符串包含一个大到无法表示为unsigned long long int值的数字,则转换的第一步不能产生可表示的值,第 8 段适用:

如果正确值超出可表示值的范围,ULLONG_MAX则返回 […] […],并将宏的值ERANGE存储在errno.

同样,几乎所有实现者都以这样一种方式解释标准,即可表示值检查仅适用于第一个转换步骤,从输入字符串中的任意精度非负整数到无符号类型。

于 2019-03-07T21:04:53.600 回答