strtoull("-1", NULL, 0)
evaluates to 18446744073709551615
, (0xFFFFFFFFFFFFFFFF
aka ULLONG_MAX
) on the systems I tested (OS/X with Apple Libc, Linux with Glibc).
Since strtoull
is supposed to check for values out of the range of the return type, why does it not return 0
for all negative values?
EDIT: the behavior around -ULLONG_MAX
seems inconsistent too:
strtoul("-18446744073709551615", NULL, 0) -> 1, errno=0
strtoul("-18446744073709551616", NULL, 0) -> 18446744073709551615, errno=34
The prevailing interpretation of section C standard (section 7.20.1.4 in C99, section 7.22.1.4 in C11, paragraph 5 in both) is that the conversion is performed in a first step, disregarding the minus sign, producing an unsigned result. This result is then negated. This is suggested by
If the subject sequence begins with a minus sign, the value resulting from the conversion is negated (in the return type).
in the standard text. Negating values of unsigned type is well-defined, so the overall result is representable if the first step resulted in a representable value. There is no subsequent error due to the negation.
On the other hand, if the input string contains a number that is so large that it cannot be represented as an unsigned long long int
value, the first step of the conversion cannot result in a representable value, and paragraph 8 applies:
If the correct value is outside the range of representable values, […]
ULLONG_MAX
is returned […], and the value of the macroERANGE
is stored inerrno
.
Again, virtually all implementers interpret the standard in such a way that the the representable value check only applies to the first conversion step, from an arbitrary-precision nonnegative integer in the input string to the unsigned type.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With