strtoull(“-1”,NULL,0)和其他负值的惊人行为

时间:2019-03-07 20:54:37

标签: c language-lawyer strtoull

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

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

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

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

1 个答案:

答案 0 :(得分:9)

C节标准(C99中的7.20.1.4节,C11中的7.22.1.4节,两者均第5段)的现行解释是,转换是在第一步中执行的,而忽略负号,产生未签名的结果。然后,该结果被否定。这是由

建议的
  

如果主题序列以减号开头,则转换结果取反(返回类型)。

标准文字中的

Negating values of unsigned type is well-defined,因此,如果第一步产生可表示的值,则总体结果可表示。由于没有,因此没有后续错误。

另一方面,如果输入字符串包含的数字太大,以致不能将其表示为unsigned long long int值,则转换的第一步不能产生可表示的值,并且第8款适用:

  

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

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