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;

+3


source to share


2 answers


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.

+4


source


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.

+1


source







All Articles