C++:
0x7FFFFFFF * 2.0 这一步会先将 0x7FFFFFFF 提升为 double 类型,计算结果也是 double 类型。再转型为 int 会截断小数部分,但整数部分的值大于 int 的取值范围了,这样转型会发生什么 C++ 标准没有规定。不过大部分编译器会直接按位保留,如果是这样的话,结果就是 0xFFFFFFFE。
而 int 是有符号整型,最高位(符号位)为 1 代表这是负数,所以为 -2。从结果看是这样的。
另外,编译器很有可能会对乘法作优化,0x7FFFFFFF 乘以 2 等于是左移动一位变成 0xFFFFFFFE,所以结果还是 -2。
Java:
算术运算时一样会进行类型转换。首先 0x7FFFFFFF * 2.0 的结果也是 double 型。这个浮点型的整数部分还是超过了 int 的范围,这样的浮点数向 int 转型时会转为int 能表示的最大数值,也就是 0x7FFFFFFF,所以结果是 2147483647。
这里你可以看出 C++ 和 Java 在处理浮点值向整型转型的不同之处:C++ 基本上是按位截断,而 Java 在浮点向整型转换时会尽量满足原本数值的含义(既然浮点值超过了int范围,那么干脆让int取最大值)
顺便一提:在 Java 中,如果你先把 0x7FFFFFFF * 2.0 的结果转为 long,再转为 int,就能得到和 C++ 一样的结果了。因为 Java 整型间转型规则和 C++ 一样:从低位截断,同样可能引起符号变化问题。 这样由于 long 能保留那个浮点型的数值,再转为 int 就和 C++ 的行为一样了,结果会是 -2.