Path: ...!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: Keith Thompson Newsgroups: comp.lang.c Subject: Re: The difference between strtol() and strtoul() ? Date: Sun, 23 Jun 2024 17:49:01 -0700 Organization: None to speak of Lines: 71 Message-ID: <87ikxztbb6.fsf@nosuchdomain.example.com> References: <20240621182839.00000dc4@yahoo.com> <20240621185314.00004fda@yahoo.com> <87o77uqktg.fsf@bsb.me.uk> <20240623121952.00005fa9@yahoo.com> <87r0cnq46s.fsf@bsb.me.uk> <20240623153219.000009b0@yahoo.com> <87jzifpth6.fsf@bsb.me.uk> <864j9jh77d.fsf@linuxsc.com> <87r0cntga9.fsf@nosuchdomain.example.com> <87o77rnrt2.fsf@bsb.me.uk> MIME-Version: 1.0 Content-Type: text/plain Injection-Date: Mon, 24 Jun 2024 02:49:05 +0200 (CEST) Injection-Info: dont-email.me; posting-host="0a690d6294358a2c4bce5879f14e083a"; logging-data="630828"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+WpJCRc8Eo0GtHe/KT/upQ" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux) Cancel-Lock: sha1:WNwKhzImSLgv4vU5ks3vEHYCLZ8= sha1:6OzF2/DVWlUjS4w4OaX7inzVK3U= Bytes: 4657 Ben Bacarisse writes: > Keith Thompson writes: >> Tim Rentsch writes: >>> Ben Bacarisse 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 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.com void Void(void) { Void(); } /* The recursive call of the void */