Sujet : Re: What is your opinion about unsigned int u = -2 ?
De : Keith.S.Thompson+u (at) *nospam* gmail.com (Keith Thompson)
Groupes : comp.lang.cDate : 03. Aug 2024, 03:04:45
Autres entêtes
Organisation : None to speak of
Message-ID : <878qxefjk2.fsf@nosuchdomain.example.com>
References : 1 2 3 4 5 6 7 8 9 10 11
User-Agent : Gnus/5.13 (Gnus v5.13)
Thiago Adams <
thiago.adams@gmail.com> writes:
Em 8/2/2024 10:25 PM, Keith Thompson escreveu:
Thiago Adams <thiago.adams@gmail.com> writes:
[...]
I am doing experiments with constexpr. What happens with overflow in
compile time? The answer is not so clear. Sometimes it does not
compile and sometimes it works as in runtime.
Your first example fails due to signed integer overflow. Your
second
example is well defined because there is no such thing as unsigned
integer overflow.
>
I need a new name other than overflow.
Wraparound, or unsigned wraparound if you want to be a little more
precise.
C23 adds this entry to the glossary (3.28):
wraparound
the process by which a value is reduced modulo 2^N, where N is the
width of the resulting type
The standard uses a superscript, which I can't easily reproduce here.
I hope it's sufficiently obvious that I'm not using ^ to mean bitwise xor.
N3220 6.2.5p11 (same or similar wording appears in earlier editions) :
A computation involving unsigned operands can never produce an
overflow, because arithmetic for the unsigned type is performed
modulo 2^N.
The expression
>
ULLONG_MAX*ULLONG_MAX/ULLONG_MAX/ULLONG_MAX
>
has the result 1 if calculated with infinite precision.
>
But the calculated value here is 0
Right. The subexpression ULLONG_MAX*ULLONG_MAX in infinite precision
would be 340282366920938463426481119284349108225 in infinite precision,
but assuming 64-bit unsigned long long the actual result is that value
modulo 2^64, or 1. Dividing 1 by ULLONG_MAX yields 0 (since integer
division truncates); dividing again by ULLONG_MAX yields 0 again.
The reduction modulo 2^64 happens on each arithmitic operation (here one
multiplication and two divisions), not on the expression as a whole.
Since ULLONG_MAX*ULLONG_MAX is 1 (more precisely 1ull), the expression
ULLONG_MAX*ULLONG_MAX/ULLONG_MAX/ULLONG_MAX
is equivalent to
1ull/ULLONG_MAX/ULLONG_MAX
#include <stdio.h>
>
int main()
{
constexpr unsigned long long ULLONG_MAX = 18446744073709551615;
constexpr unsigned long long r =
ULLONG_MAX*ULLONG_MAX/ULLONG_MAX/ULLONG_MAX;
printf("%llu", r);
}
-- Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.comvoid Void(void) { Void(); } /* The recursive call of the void */