Subtract unsigned values ​​- unexpected result

I have two variables ( test1 and test2 ), both unsigned. I need to check which one is bigger.

I am trying to figure out what happens if an overflow occurs.

My first test was done using type uint8_t ( char ):

 #include <stdio.h> #include <stdint.h> #include <math.h> int main() { uint8_t test1 = 0; printf("test1 = %d\n", test1); uint8_t test2 = pow(2, 8 * sizeof(test1)) - 1; //max holdable value of uint8_t printf("test2 = %d\n", test2); uint8_t test3 = test1 - test2; printf("test1 - test2 = %d\n", test3); if ((test1 - test2) == 0) printf("test1 == test2\n"); if ((test1 - test2) > 0) printf("test1 > test2\n"); if ((test1 - test2) < 0) printf("test1 < test2\n"); if (test3 == 0) printf("test1 == test2\n"); if (test3 > 0) printf("test1 > test2\n"); if (test3 < 0) printf("test1 < test2\n"); return 0; } 

output:

 test1 = 0 test2 = 255 test1 - test2 = 1 test1 < test2 test1 > test2 

What? Creating an expression and storing it in a variable and then checking it is different from checking subtraction on the fly?

My second test was performed using the uint32_t ( long ) data type:

 #include <stdio.h> #include <stdint.h> #include <math.h> int main() { uint32_t test1 = 0; printf("test1 = %d\n", test1); uint32_t test2 = pow(2, 8 * sizeof(test1)) - 1; //max holdable value of uint32_t printf("test2 = %lu\n", test2); uint32_t test3 = test1 - test2; printf("test1 - test2 = %d\n", test3); if ((test1 - test2) == 0) printf("test1 == test2\n"); if ((test1 - test2) > 0) printf("test1 > test2\n"); if ((test1 - test2) < 0) printf("test1 < test2\n"); if (test3 == 0) printf("test1 == test2\n"); if (test3 > 0) printf("test1 > test2\n"); if (test3 < 0) printf("test1 < test2\n"); return 0; } 

output:

 test1 = 0 test2 = 4294967295 test1 - test2 = 1 test1 > test2 test1 > test2 

What??? Now make a replacement and save it in a variable, and then check it, just like checking for subtraction on the fly?

SO I expected that subtraction between unsigned values ​​(without an explicit cast) ALWAYS returns the value> = 0. But executing a substring inside IF produces unexpected results.

Now I am confused. Can someone explain this behavior to me?

+6
source share
3 answers

In connection with the type promotion, your uint8 will be advertised on the int platform, which is likely to be larger than the 8-bit (usually 32-bit) in most modern "Computer".

this line:

 if ((test1 - test2) < 0) 

if equivalent

 if ((int)((int)test1 - (int)test2) < 0) = -255 < 0 

which is true.

However for this line

 uint8_t test3 = test1 - test2; 

he is equivalent

 uint8_t test3 = (uint8_t)((int)test1 - (int)test2); //(uint8_t)(-255) = 1!!; 

So, as test1 - test2 < 0 , so test3 > 0 (welcome to the world of computers!) Correctly!

This explains your result.

But for uint32 , because it has a "higher" rank than native int , so it does not "advance" and remains like uint32 all the time, or, in other words,

this line:

 if ((test1 - test2) > 0) 

if equivalent

 if ((uint32_t)((uint32_t)test1 - (uint32_t)test2) > 0) = large positive number > 0 

and this line

 uint32_t test3 = test1 - test2; 

equivalently

 uint32_t test3 = (uint32_t)test1 - (uint32_t)test2; //also large positive number 

Thus, you have both test1 - test2 > 0 , and test3 > 0 .

So, in your two cases, both can be correct only when working on an 8-bit machine. Or, suppose, in the future, the native int will be 64-bit, then both cases will be correct too ...

+5
source

A few secret type promotion rules apply . In the first example, where the operands are uint8_t , for the expression:

 test1 - test2 

both operands implicitly advance to int before subtraction, and the expression itself is of type int .

+9
source

Actually, when you subtract how

 0 - 255; // It results -255 

and you try to save it in unsigned int so that it is saved as follows:

 -1 in Unsigned int (1 Byte) as 255 -2 as 254 -3 as 253 . . . -255 as 1 

That is why you got it. The reason is that he stores variables in which he uses 1 or 2 compliments, has no idea, but he is sure that this is due to the fact that

+1
source

All Articles