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, 02:25:30
Autres entêtes
Organisation : None to speak of
Message-ID : <87h6c2fldh.fsf@nosuchdomain.example.com>
References : 1 2 3 4 5 6 7 8 9
User-Agent : Gnus/5.13 (Gnus v5.13)
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.
constexpr int i = 1073741823;
constexpr int i2 = i*3/3; /*does not compile*/
The `constexpr` means that the initializer must be a constant
expression. `i*3/3` is not a constant expression, because `i*3` is not
a constant expression, because its result is not in the range of
representable values for its type, violating the constraint in N3220
6.6p4. (Assuming 32-bit int; if int is wider than 32 bits there's no
overflow and i2 is 1073741823 .)
But this compiles and outputs
>
#include <stdio.h>
>
int main()
{
constexpr signed char i = -2;
constexpr unsigned long long u = 0ull+i;
printf("%ull", u); /*prints 4294967294*/
}
No, the printf has undefined behavior; it prints "4294967294ll" on my
system. The format for unsigned long long is "%llu", not "%ull". You
have a "%u" for unsigned int followed by a literal "ll". It's probably
printing the low-order 32 bits of the 64-bit value. (You should also
have a newline at the end of the output.)
Fixing that problem :
#include <stdio.h>
int main() {
constexpr signed char i = -2;
constexpr unsigned long long u = 0ull+i;
printf("%llu\n", u); /*prints 4294967294*/
}
The output is "18446744073709551614" (assuming unsigned long long is 64
bits, which it is in every implementation I'm aware of).
There's no overflow. `0ull` is of type `unsigned long`, value
zero. `i` is of type `signed char`, value -2. For the addition, the
usual arithmetic conversions cause the right operand to be converted
from signed char to unsigned long long, yielding ULLONG_MAX-2,
or 18446744073709551614, or 0xfffffffffffffffe .
-- Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.comvoid Void(void) { Void(); } /* The recursive call of the void */