Type of an expression

c, c++, language-lawyer

Solution

Conversions follow the integer conversion rank principle. In an nutshell, integral operands are handled as follows.

First, each operand smaller than `int` is converted to `int` (if all values of the original type fit), or to `unsigned int` if not.

After that, if the (possibly converted) operand types are:

exactly the same, no conversion happens.

of the same size, unsigned takes precedence.

of different size, smaller is converted to larger. If larger is unsigned, smaller is converted to unsigned as well.

This conversion turns the operands into the same type, which is the type of the result as well.

It's covered by `[expr]§9` of the C++11 standard. It also relates closely to `[conv]` and `[conv.rank]`. To which operators exactly this applies is covered in the individual operators' descriptions in subchapters of `[expr]`.

Problem

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?

Original source

Related problems