有符号字符的乘法问题

时间:2011-04-30 10:04:58

标签: c++ visual-studio

讨论this回答我发现以下代码在visual studio中打印-11。为什么?在我看来,尽管在乘法过程中溢出,它仍应打印两个1

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;

4 个答案:

答案 0 :(得分:4)

c1可能有-128之类的值。在乘法中,整数提升将导致c1c2在执行操作之前转换为类型int

c1 * c2将成为值int的{​​{1}},因此128将是c1 * c2 / c1,其值为int

第一个输出的

-1对我来说是正确的。

对于第二个版本,通常-1的结果分配不适合c1 * c2并且会转换为实现定义的结果,可能是signed char而不是-128 {1}}。

答案 1 :(得分:2)

整数溢出被认为是UB。这意味着编译器会将(c1 * c2 / c1)视为完全等同于c2

您可以查看this以获取更多信息。

答案 2 :(得分:0)

c1 * c2int乘法(标准中为5/9)。我们知道在MSVC上CHAR_BIT是8并且它对签名类型使用了两个补码表示,所以我们知道值:-128 * -1是128。

128 / -128是-1,所以这是第一个排序的结果。

-CHAR_MIN分配给signed char具有实现定义的结果(4.7 / 3),但我们知道在MSVC中结果为-128。然后-128 / -1为1,这是排序的第二个结果。

答案 3 :(得分:0)

第一种情况,将显式扩展为int:

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

第二种情况,分配给中间变量等同于

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

(编译器对int进行的隐式强制转换是明确的。)

使用二进制补码,将类型的最大负值乘以-1会使值保持不变,如果它被限制为相同的位数。所以,第二个例子,c1 * c2 == c1。即使乘法是以int形式完成的,它也会被强制转换为char的宽度。

在第一个示例中,整个calaulation是作为int完成的,因此操作有更多位可以使用,因此不会发生截断。这里,c1 * c2 ==(c1 * -1)== -c1。因此结果不同。