When the compiler sees smallValue * value
, it must decide what the data type of the result is going to be, given the input data types signed
(8 bits) and unsigned int
(usually, either 16 or 32 bits). The rules of C++ state that in this situation, the result will be unsigned. Therefore, the value of smallValue * value
cannot be -500
, as you are expecting; instead, the value -500
is interpreted as a POSITIVE number.
Furthermore, you are here multiplying an 8-bit value by a value that is typically either 16- or 32-bit. The rules of C++ in this scenario state that the smaller-storage value will first be cast to the same size as the larger; so in this case the result of smallValue * value
will indeed be large enough to store a number of magnitude 500
.
Proceeding to multiply by the unsigned quantity anotherSmallValue
(=1) results in another unsigned
with the same value.
Because you are using auto
, the return type is therefore deduced to be unsigned
.
Simply by casting back to a signed
(by, for example, defining the value test
as an int
, rather than an auto
, will in turn typically cast the result of the entire operation back to a signed
value, without changing the bits internally; this will then properly display -500
, as you expect; however, as other posters have noted, this is rather dangerous in theory because it's not techincally guaranteed to work, although it usually will work this way with today's compilers.