【发布时间】:2026-02-01 22:50:01
【问题描述】:
考虑以下代码:
#include <iostream>
using namespace std;
int main() {
// the following is expected to not print 4000000000
// because the result of an expression with two `int`
// returns another `int` and the actual result
// doesn't fit into an `int`
cout << 2 * 2000000000 << endl; // prints -294967296
// as such the following produces the correct result
cout << 2 * 2000000000U << endl; // prints 4000000000
}
我尝试将结果转换为不同的整数类型,但遇到了一些奇怪的行为。
#include <iostream>
using namespace std;
int main() {
// unexpectedly this does print the correct result
cout << (unsigned int)(2 * 2000000000) << endl; // prints 4000000000
// this produces the same wrong result as the original statement
cout << (long long)(2 * 2000000000) << endl; // prints -294967296
}
我预计以下两个语句都不会产生正确的结果,为什么一个成功而另一个没有?
【问题讨论】:
-
尝试将 LL 后缀添加到数字,数字
2 * 2000000000是一个表达式,它被评估为int(溢出)然后转换为long long -
将 int 转换为 unsigned int 将起作用,因为这些位是相同的,只是程序理解这些位的方式在转换前后有所不同。
-
溢出后,任何事情都可能发生,包括通常你想发生的事情,只是为了迷惑你;-)
-
@JonTaylor:不。转换是在 values 而不是位上完成的。从有符号到无符号的转换是以无符号整数中位的最大值为模完成的。事实上,在二的互补机器上,这意味着简单地以不同的方式解释位,这一事实是简洁但无关紧要的。重要的是(经过一些数学运算)
2^32 - 294967296 = 4000000000。无论位表示如何,它都可以工作。 -
@GManNickG:不过,关键是
2 * 2000000000会导致-294967296,这在很大程度上取决于系统和位表示(特别是因为在这种情况下它无论如何都是未定义的行为) .但是,是的,使魔术起作用的不是演员(就像您正确指出的那样);这是 2 对int的补充,以及处理溢出的方式使其工作。只是想让它更清楚一点。
标签: c++ casting integer integer-overflow