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 / c开发者_开发技巧1 << endl;
c1
might have a value like -128
, say. In the multiplication, integer promotions will cause both c1
and c2
to be converted to type int
before the operation is performed.
c1 * c2
is then going to be a int
with value 128
so c1 * c2 / c1
is going to be an int
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 a signed char
and will convert to an implementation-defined result, perhaps -128
instead of 128
.
Integer overflow is considered UB. This means that the compiler will consider (c1 * c2 / c1)
to be completely equivalent to c2
.
You can check this for additional info.
c1 * c2
is an int
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 a signed 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.
The first case, making upscaling to an int explicit:
cout << ((int)c1 * c2 / c1 << endl;
the second case, assigning to an intermediate variable is equivalent to
cout << ((signed char)((int)c1 * c2)) / c1 << endl;
(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.
精彩评论