Discussing this answer I find out that the code bellow prints -1
and 1
in visual studio. Why? In my opinion it should print two 1
s despit overflow during multiplication.
signed char c1 = numeric_limits<signed char>::min();
signed char c2 = -1;
cout << c1 * c2 / c1 << endl;
signed char result = c1 * c2;
cout << result / c1 << endl;
c1
might have a value like-128
, say. In the multiplication, integer promotions will cause bothc1
andc2
to be converted to typeint
before the operation is performed.c1 * c2
is then going to be aint
with value128
soc1 * c2 / c1
is going to be anint
with value-1
.-1
for the first output looks correct to me.For the second version, typically the assignment of the result of
c1 * c2
won't fit into asigned char
and will convert to an implementation-defined result, perhaps-128
instead of128
.c1 * c2
is anint
multiplication (5/9 in the standard). We know that CHAR_BIT is 8 on MSVC and that it uses two's complement representation for signed types, so we know the value: -128 * -1 is 128.128 / -128 is -1, so that's the first result sorted.
Assigning
-CHAR_MIN
to asigned char
has implementation-defined results (4.7/3), but we know in MSVC the result is -128. Then -128 / -1 is 1, so that's the second result sorted.Integer overflow is considered UB. This means that the compiler will consider
(c1 * c2 / c1)
to be completely equivalent toc2
.You can check this for additional info.
The first case, making upscaling to an int explicit:
the second case, assigning to an intermediate variable is equivalent to
(Implicit casts to int done by the compiler made explicit.)
With two's complement, multiplying the largest negative value of a type by -1 leaves the value unchanged if it is restricted to the same number of bits. So, the second example, c1*c2 == c1. Even though the multiplication is done as an int, it is cast back to the width of a char.
In the first example, the entire calaulation is done as an int, so the operation has more bits to work with, and so the truncation doesn't occur. Here, c1*c2 == (c1*-1) == -c1. Hence the different result.