开发者

Problem with multiplication of signed chars

开发者 https://www.devze.com 2023-03-02 09:55 出处:网络
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 1s despit overflow during multiplication.

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 1s 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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号