整数转换问题

时间:2012-11-23 10:16:47

标签: c++ integer type-conversion uac

int left = std::numeric_limits<int>::min();
int right = -1;
//the code below instead of give one more than int_max gives: 18446744071562067968
unsigned long long result = left * right;

我试图查找UAC但是根据UAC规则,这应该产生正确的输出。任何想法结果不正确的想法?

3 个答案:

答案 0 :(得分:4)

两个操作数均为int,因此算术在int类型内执行;操作的结果溢出了int的范围,因此结果是未定义的。

要获得预期的结果,首先将一个操作数强制转换为long long

 unsigned long long result = left * (long long) right;

这仍然是潜在的未定义行为;尽可能早地转换为无符号算术更安全(因为无符号算术包装并且不会溢出):

unsigned long long result = left * (unsigned long long) right;

请注意,您得到的结果是0xffffffff80000000;这表示该操作的实际结果为std::numeric_limits<int>::min()类型int,然后进行符号扩展并转换为unsigned long long

答案 1 :(得分:4)

将有符号2的补码int的最小值乘以-1是未定义的行为,因为结果超出了类型的范围。

在这种情况下,您的输出与-2147483648的结果一致,即溢出似乎已经缠绕。您不能依赖签名类型的环绕,只能使用无符号类型。

将计算结果分配给unsigned long long并不会改变执行计算的类型。一旦进行乘法,就会丢失。因此,在乘法之前将其中一个操作数转换为unsigned long long

答案 2 :(得分:0)

原因是乘法是按int提交的。

这两个参数都是int,因此乘法会产生int年龄,而你是对的,它给出了int_max + 1,相当于int_min = - 2147483648。所以它实际上是-2147483648,但是对于无符号长整数,它相当于18446744071562067968,参见十六进制代码:

                       int_min =         80000000 
(unsigned long long) (int min) = ffffffff80000000