In both C and C++, in the vast majority of cases, the type of an expression is determined from the expression itself, without regard to the context in which it appears.
int var = 5u - 10;
5u
is of type unsigned int
; 10
is of type int
. The rules for the -
operator cause the int
argument to be converted to unsigned int
, making the expression equivalent to 5u - 10u
. The result is UINT_MAX + 1 - 10
, a very large number. The initialization implicitly converts this from unsigned int
to signed int
. Since that value (almost certainly) isn't representable as an int
, the result of the conversion is implementation-defined. In nearly all existing implementations, the conversion simply reinterprets the unsigned representation as if it were a signed value, resulting in -5
. (This applies to systems that use a two's-complement representation for negative values; the resulting simplicity of signed/unsigned conversions is one of the reasons two's-complement is so widely used.)
Note that it would not be possible for var
to have the value 4294967291
; the largest value that an int
can hold on your system is (probably) 2147483647
.
auto var = 5u - 10;
5u - 10
is evaluated the same way as before, resulting in an unsigned int
result of UINT_MAX + 1 - 5
, or 4294967291
on your system. The auto
means that var
takes on the type of the expression, unsigned int
, so no conversion is performed. (On a system with 16-bit int
, the result would be 65531
.)
In answer to your question, the constant 10
is converted from int
to unsigned int
in both cases.