Unexpected results on difference of unsigned ints
I was surprised that this function produces different values ββfor dif1 and dif2
void test()
{
unsigned int x = 0, y = 1;
long long dif1 = x - y;
long long dif2 = (int)(x - y);
printf("dif = %lld %lld",dif1,dif2);
}
Is this the correct behavior? In calculating dif1, it first promotes a 32-bit unsigned difference with a 64-bit unsigned value and then adds a sign. Is this standard behavior not specified by the language, or is it a compiler error? Is the second form a guaranteed performance of -1 or before the compiler implementation? I think the safest construction is: long long dif3 = (long long) x - (long long) y;
source to share
The first is definitely definite, assuming that it is long long
wider than unsigned int
. If this is not the case, then the task gives the same problem as the second part of the answer.
long long dif1 = x - y;
Unsigned integers will wrap around and you will get the maximum value that can be stored in an unsigned int.
6.2.5 p9: computation using unsigned operands can never overflow because a result that cannot be represented by the resulting unsigned integer is modulo a number that is greater than one largest value that can be represented by the resulting type.
As for the second
long long dif2 = (int)(x - y);
implementation defined:
6.3.1.3 p3: Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is emitted.
In this case, the maximum value for unsigned int
cannot be represented in int
ant, the above rule applies.
source to share
There is nothing surprising.
unsigned int x = 0, y = 1;
long long dif1 = x - y;
long long dif2 = (int)(x - y);
The second has one difference from the first:
Bringing to signed
.
Listing is defined as a possible preservation of values ββ(impossible, since UINT_MAX
greater than INT_MAX
), and the rest is implemented (although a trap is allowed).
If we have a cast 2s complement (probably), the result is a cast -1
.
Then we have an assignment of a more widely signed type that always retains a value.
source to share