整数转换问题

Issue with Integer Conversion

本文关键字:问题 转换 整数      更新时间:2023-10-16
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 规则,这也应该产生正确的输出。知道为什么结果不正确吗?

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

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

将计算结果分配给unsigned long long不会更改执行计算的类型。一旦你做了乘法,你就输了。因此,在相乘之前将其中一个操作数转换为 unsigned long long

两个操作数都是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

Tha 原因是乘法是根据 int 提交的

这两个参数都是int的,所以乘法给出了一个int agein,你是对的,它给出了int_max + 1,这与int_min=-2147483648相等。所以它实际上是 -2147483648,但对于无符号的长长,它等同于18446744071562067968,请参阅十六进制代码:

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