Two's complement with unsigned integers

Hello,

I was running this little experiment on codepad.org, to understand what happens when negative numbers (using two's complement form) are assigned to unsigned integers. But the outcome is not as I expect. Perhaps you guys can shed some light on why.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>

using namespace std;

int main()
{
    unsigned short u = 10, u2 = 42;
    cout << "sizeof(unsigned short): " << sizeof(u) * 8 << " bits\n";
    cout << u2 - u << endl;
    cout << u - u2 << endl;  // I expect this to produce 65504,
                             // but the result is -32. 

    return 0;
}
You are right this will give you -32 because how does compiler comes to know
what is the type of u-u2.
1
2
3
unsigned short u = 10, u2 = 42;
unsigned short a = u - u2;
cout << u - u2 << endl; // this will give you 65504 
I thought that the compiler would know because both operands are of the same type - and therefore assume that no casting/conversion is necessary.

If I run the same experiment with unsigned int, I get the expected result. The size of an unsigned int in my system is 4 bytes (32 bits) and the result from the u-u2 expression is 4294967264 (11111111111111111111111111100000 in binary), that is, unsigned. So in this case the code produces the result I had expected, but for unsigned short (16 bits) it seems to treat the result (1111111111100000 in binary) as a signed value. It's confusing to me.
This is a peculiarity of C/C++ language(s).

The compiler performs the integral promotion on both operands of the additive operator -. That means that objects of types that have the rank less than the rank of the type int are converted to the type int. The rank of unsigned short is less than the rank of int so u and u2 are converted to int. After that the expression u - u2 is executed that also has type int because the both its operands have type int after the integral promotion.

Compare your code with the following code

1
2
3
unsigned int u = 10, u2 = 42;

std::cout << u - u2 << std::endl;


Here the both operands have the type unsigned int. The rank of unsigned int is not less than the rank of int. So the integral promotion will not be performed and you will get a positive number will be displayed on the console as the result of the operation.
Last edited on
@squarehead.. after explanation of vald from moscow you might get why we need
unsigned short a = u - u2;.
Last edited on
I'm guessing this is a compiler/system specific peculiarity. Perhaps in a 64-bit system the operands would be converted to 64-bit values at calculation time, because the int type is represented by 64 bits in memory?

Thank you both for your teaching me something new today!
Topic archived. No new replies allowed.