Problem with signed character multiplication

By discussing this answer, I find out that the code below prints -1 and 1 in visual studio. What for? In my opinion, it should print two descriptor 1 overflows 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; 
0
source share
4 answers

c1 may matter, for example, -128 . When multiplied, whole promotions will cause both c1 and c2 be converted to int type before the operation is completed.

c1 * c2 will then be int with a value of 128 , so c1 * c2 / c1 will be int with a value of -1 .

-1 for the first output looks correct to me.

For the second version, as a rule, assigning the result c1 * c2 will not fit into the signed char and will be converted to the result determined by the implementation, possibly -128 instead of 128 .

+4
source

Integer overflow is considered UB. This means that the compiler will consider (c1 * c2 / c1) fully equivalent to c2 .

You can check this one for more information.

+2
source

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 view representations for signed types, so we know the value: -128 * -1 - 128.

128 / -128 is -1, so the first result is sorted.

Assigning -CHAR_MIN a signed char has the results defined by the implementation (4.7 / 3), but we know that in MSVC the result is -128. Then -128 / -1 is 1, so the second result is sorted.

0
source

The first case doing scaling for int explicit:

 cout << ((int)c1 * c2 / c1 << endl; 

second case, assigning an intermediate variable is equivalent

 cout << ((signed char)((int)c1 * c2)) / c1 << endl; 

(The implicit int casts made by the compiler are made explicit.)

With two additions, multiplying the largest negative type value by -1, the value remains unchanged if it is limited to the same number of bits. So, the second example: c1 * c2 == c1. Although the multiplication is done as an int, it returns to the width of the char.

In the first example, the entire calorie is executed as an int, so the operation has more bits to work, and therefore truncation does not occur. Here c1 * c2 == (c1 * -1) == -c1. Hence another result.

0
source

All Articles