Consider the following part of a C++ program; the values printed to the console are given as comments.
{ // case 1
unsigned int x = 10;
unsigned int y = 20;
std::cout << "u/u x - y: " << x-y << std::endl; // 4294967286
}
{ // case 2
int x = 10;
int y = 20;
std::cout << "s/s x - y: " << x-y << std::endl; // -10
}
{ // case 3
unsigned int x = 10;
int y = 20;
std::cout << "u/s x - y: " << x-y << std::endl; // 4294967286
}
{ // case 4
int x = 10;
unsigned int y = 20;
std::cout << "s/u x - y: " << x-y << std::endl; // 4294967286
}
I'm trying to figure out how C++ (tried with gcc 4.7.2) defines the type (more specifically, its signedness) from an expression. For cases 1, 3, and 4, the usual arithmetic conversions should promote both values to an unsigned int:
10 = b00000000000000000000000000001010
20 = b00000000000000000000000000010100
Then, it would do a 2's complement to get -20 and add it:
10 = b00000000000000000000000000001010
-20 = b11111111111111111111111111101100
b11111111111111111111111111110110
Interpret that as an unsigned integer, and you get 4294967286 -- very well.
Obviously, you get the same calculation/result for case 2; however, the usual arithmetic conversions should result in both operands being interpreted as a signed int, and also the result seems to be interpreted as a signed integer.
From this, I'm deducing, that, if the operands are signed after the usual arithmetic conversions, the result is signed. Otherwise, the result is unsigned.
So, my questions are:
- Is my deduction correct?
- Where does the standard define this? I cannot find any reference to this in the C or C++ standard.
- What about other operations? I suspect that
+
,*
, etc. will work the same way, but what about shift and logical operations?
Edit: This seems related to C++11 type of (signed + unsigned)?, but the crucial part for my question seems to be missing from the accepted answer there: will the result of an expression always be the type of both operands after the usual arithmetic conversions?