C ++ implicit data type conversion from unsigned to signed

I know that lower datatypes are passed to higher datatypes (e.g. int -> unsigned int -> float -> etc.), but I'm not sure about the following:

int var = 5u - 10; // var = -5
auto var = 5u - 10; // var = 4294967291

      

5u unsigned, but in the first case, why -10 (signed integer) is not converted to an unsigned value, and in the second case? In the first case, the signed value is not converted to unsigned and this is odd to me

+3


source to share


4 answers


There is no "signed integer literal": 5u - 10

it is actually subtracting 10 from 5u.

The result (of the subtraction) is unsigned and goes into overflow, resulting in "5 numbers less than overflow 0" (4294967291 = 2 32 -5)



The first statement initializes int

, so a compile-time immutable constant is interpreted as int. The result is correct (-5) because your hardware uses 2s's complement arithmetic. (-5 and 4294967291 are the same 32-bit pattern)

The second statement initializes a variable whose type is called by the literal. And this unsigned

.

+3


source


First of all, since you are using auto

, the compiler will choose unsigned

in the second example.

Signed and unsigned numbers are stored identically internally. This is just a way of interpreting the number as it is printed, which makes a difference [and in comparison, since "negative" signature numbers are below 0, where unsigned numbers cannot be less than zero] - flagged signature numbers if they are "negative" and printed as a sign minus and negative original number. Unsigned numbers are treated only as internal representation when printed.



So, the values ​​you see are just two different representations of the same number - signed and unsigned respectively.

+2


source


The right-hand sides of both of your examples work entirely on an unsigned type domain. That is, both expressions 5u - 10

behave the same, which is not surprising since they are the same. There is no conversion to int

(as you seem to be wrongly suggesting) in the expression 5u - 10

anyway.

The expression 5u - 10

always evaluates in the domain of an unsigned type and produces an unsigned result equal to UINT_MAX + 1 - 5

. In the first initialization, you try to force that value into a type variable int

, resulting in an overflow with certain behavior. In your case, your implementation behaved like the var

resulting value -5

. In other words, the fact that you ended up with -5

in var

has no definitive explanation in the realm of abstract C ++. The result you are seeing is just a quirk of your compiler. In another compiler, the first initialization might result in a different value in var

.

In the second case, the type of the expression (which, again, unsigned

) becomes the type of a variable that is initialized to an unsigned value without any overflows.

+2


source


In 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

has a type unsigned int

; 10

has a type int

. The rules for the operator -

result in the conversion of the argument int

to unsigned int

, which is equivalent to an expression 5u - 10u

. The result UINT_MAX + 1 - 10

is a very large number. Initialization implicitly converts this value from unsigned int

to signed int

. Since this value is (almost certainly) not represented int

, the result of the conversion is implementation-defined. In almost all existing implementations, the conversion simply reinterprets the unsigned representation as if it were a signed value, resulting in-5

... (This applies to systems using two's complement representation for negative values, and as a result, the ease of signed / unsigned conversions is one of the reasons two's complement is so widely used.)

Note that var

it would be impossible for it to matter 4294967291

; the highest value int

your system can hold (possibly) 2147483647

.

auto var = 5u - 10;

      

5u - 10

is evaluated the same way as before, the result is the result unsigned int

UINT_MAX + 1 - 5

or 4294967291

in your system. auto

means it var

takes on the type of the expression unsigned int

, so no conversion is done. (On a 16-bit system, the int

result will be 65531

.)

In response to your question, the constant is 10

converted from int

to unsigned int

in both cases.

+1


source







All Articles