Sujet : Re: The difference between strtol() and strtoul() ?
De : Keith.S.Thompson+u (at) *nospam* gmail.com (Keith Thompson)
Groupes : comp.lang.cDate : 24. Jun 2024, 01:49:01
Autres entêtes
Organisation : None to speak of
Message-ID : <87ikxztbb6.fsf@nosuchdomain.example.com>
References : 1 2 3 4 5 6 7 8 9 10 11 12
User-Agent : Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux)
Ben Bacarisse <
ben@bsb.me.uk> writes:
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
Ben Bacarisse <ben@bsb.me.uk> writes:
[range questions for strtol(), etc]
>
I think there /is/ something problematic with the wording about the
negation. It happens "in the return type" but how can
9223372036854775808 be negated in the type long long int? OK, the
negated value can be /represented/ in the type long long int but that's
not quite the same thing. On the othee hand, for the unsigned return
types, the negation "in the return type" is what produces ULONG_MAX for
"-1" when the negated value, -1, can't be /represented/ in the return
type. It's a case where, over the years, I've just got used to what's
happening.
>
I understand what these functions do, but their specification in the
C standard is a little off. To my way of thinking the impact is
minimal, but the specified behavior is either unequivocally wrong or
there are some cases that give rise to undefined behavior.
>
Can you give an example where the specified behavior causes undefined
behavior?
>
I don't want to pre-empt Tim's answer, but the wording that bothers me
is
>
"If the subject sequence begins with a minus sign, the value resulting
from the conversion is negated (in the return type)."
>
For strtoll("-9223372036854775808", 0, 0) the value resulting from the
conversion is 9223372036854775808 which can not even be represented in
the return type, so how can it be negated "in the return type"?
Understanding the significance of your example requires recognizing
that number, which I didn't immediately.
I'll assume in the following that long long and intmax_t are 64 bits,
2's-complement, no padding bits.
9223372036854775808 is 2**63, and is mathematically equal to
LLONG_MAX+1.
-9223372036854775808 is mathematically equal to LLONG_MIN,
but the behavior of the strtoll() call is specified in
terms of computing 9223372036854775808 (outside the range of
long long) and then negating it. It's obvious (I think) that
strtoll("-9223372036854775808", 0, 0) *should* return LLONG_MIN and
not set errno to ERANGE (which it does in every implementation I've
tried), but the way the standard describes it involves a semantically
impossible operation.
-9223372036854775808 is the mathematical value of LLONG_MIN, but
it's not a valid C expression (so <limits.h> typically has to use
some workaround like (-LLONG_MAX-1)) -- but we expect strtoll to
handle it in the obvious way.
Beyond this example, the wording is also problematic
for out-of-range values with a leading '-' sign, such as
strtoll("-9999999999999999999", 0, 0). The result should be
LLONG_MIN with errno==ERANGE, but again the standard says "the value
resulting from the conversion is negated (in the return type)",
which is not actually possible. The same applies to strtoull().
It's not surprising that implementers have inferred the intent
even if the standard doesn't precisely state it. Still, I'd like
to see the wording made more precise.
-- Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.comvoid Void(void) { Void(); } /* The recursive call of the void */