The last example in this tutorial regarding Implicit type conversion states that std::cout << 5u - 10;
will produce 4294967291
rather than -5
due to type conversion.
I tried this in both C and C++. The result in C++ was as promised, however when using C (printf("%d\n", 5u - 10);
) the result was -5
.
What happened?

- 1,091
- 7
- 18
-
1C is not type safe, hence [using the wrong format string invokes undefined behavior](http://stackoverflow.com/q/14504148/995714) – phuclv Sep 01 '15 at 16:56
2 Answers
In the C example there is no type conversion whatsoever. C just evaluates the expression 5u - 10
and pushes the result onto the stack. Then printf sees a type character and interprets the value on the stack as such when printing it. The type character is d
(%d
) meaning "decimal integer" and hence the position on the stack is retrieved as an int and is printed as (signed) decimal.
Would the type character be for example ld
(%ld
), the position on the stack would be retrieved as a long, even if only an int was pushed, and that would be printed as a (signed) decimal number. Again, there is no type conversion whatsoever (there will just be a nonsense number printed).

- 25,048
- 4
- 23
- 41
-
There is integer promotion going on for the calculation. As to the `printf`, I agree with you - I phrased it incorrectly. – levengli Sep 02 '15 at 05:03
-
@levengli, I believe there is no "promotion" to either signed or unsigned int. Calculations are done by default in the width of integers (signed or unsigned). In the constant expression, from the number 5, whether signed or unsigned, the number 10 is subtracted. The subtraction "wraps the bits" and results in a number that is large if interpreted as unsigned and is -5 when interpreted as signed. – Paul Ogilvie Sep 02 '15 at 09:32
-
When performing arithmetic, both sides of the operator need to be of the same data type. `5u` is `unsigned` while `10` is `signed` (default). As a result, integer conversion takes place. See section "6.3.1.8 Usual arithmetic conversions" of the c99 spec – levengli Sep 02 '15 at 13:39
-
@levengli, that is just a theoretical argumentation. The bitwise representation of unsigned 5, signed 5 and the bitwise representation of unsigned 10 and signed 10 are identical. Hence no real promotion takes place. I don't care if the compiler would internally use floating point to calculate the constant expression, as long as it puts the correct result in the object file (an integer width set of bits that can be interpreted as unsigned 4294967291 or signed -5). – Paul Ogilvie Sep 02 '15 at 14:03
-
you are correct in the case of positive numbers, `int` and values that are not larger than 2^31 – levengli Sep 02 '15 at 18:28
A little more thought brought upon the realization that the problem was with the printf
rather than the conversion itself.
Notice that what was written was printf("%d")
. This performed yet another conversion back to signed int
, which is why I saw the result of -5
.
When testing with printf("%u")
, the promised result (4294967291
) was shown.
To cap it off, printf("%X")
resulted in FFFFFFFB
which means both those values, depending on a signed or unsigned interpretation.

- 1,091
- 7
- 18
-
2
-
5`printf` doesn't perform conversions based on the format specifier. It assumes the data is of the right type, and causes undefined behaviour otherwise. – juanchopanza Sep 01 '15 at 16:11
-
Indeed - there is ***no difference*** between how `int` and `unsigned` are represented internally. There is no "conversion" going on, only the handling of the the same data according to type. – Weather Vane Sep 01 '15 at 16:32
-
Why do people upvote this? Run the code in a compiler that doesn't use 2's complement, surprise things will happen and you'll see that no conversion is applied. `printf` has no notion of type and simply treat the bytes as the format specified – phuclv Sep 02 '15 at 12:40