将两个整数相乘并将结果存储在浮点变量中时,结果可以流过吗?

时间:2015-03-12 15:54:38

标签: c++

我一直想知道这样的代码是如何运作的:

int a = 10;
int b = 20;
double c = a * b;

如果整数太大以至于a*b大于可以存储在整数类型变量中的最大值,那该怎么办?编译器会注意到目标类型可以包含更大的值并首先将值转换为double,还是乘法只会流过/回绕?

4 个答案:

答案 0 :(得分:2)

当乘以两个整数值时,编译器本身永远不会将结果转换为浮点类型。也就是说,如果您将两个int值相乘,结果也将是int值。

所以,你的代码有效的是:

int a = 10;
int b = 20;
int tmp = a * b; // Result is actually an int
double c = (double)tmp; // Convert to a double.

因此,只有在无法存储在int中时,结果才会溢出。转换和分配到double只能在计算结果后才能完成。

答案 1 :(得分:1)

答案是否定的。编译器不会将整数转换为双精度,因为编译器不运行任何代码。当程序执行时,整数将被乘法(并且可能溢出)并且结果将存储在'c'中,但'c'仅为双精度的事实意味着它足够大以保持结果。在放入'c'之前,溢出就已经发生了。

如果编译器能够更改数据类型,则意味着编译器不仅可以通过更改数据类型来影响最终的程序大小,还可以在代码的其他部分中弄乱数据类型期望。例如,如果您希望对一个整数进行位移,可能会发生不好的事情,但是在运行时,由于编译器决定更改您的数据类型,因此您需要进行双位移位。恐怖!

答案 2 :(得分:0)

乘法的结果将由usual arithmetic conversions确定,并且只考虑乘法本身的操作数,来自草案C ++标准:

  

*和/的操作数应具有算术或未范围的枚举类型; %的操作数应该有   整数或无范围的枚举类型。通常的算术转换是在操作数上执行的   并确定结果的类型。

如果结果无法用转换后的类型表示,那么它将调用未定义的行为:

  

如果在评估表达式期间,结果未在数学上定义或不在范围内   其类型的可表示值,行为未定义

因此您应该在操作之前检测到溢出并进行相应处理,请参阅Will gcc skip this check for signed integer overflow?

答案 3 :(得分:0)

  

如果整数太大而a*b大于最大值,该怎么办?   值可以存储在整数类型的变量中。

有符号整数溢出是未定义的行为。

  

编译器是否会注意到目标类型可以包含更大的值   并首先将值转换为double,或者将乘法转换为double   只是流过/环绕?

由于它未定义,因此允许编译器执行任何操作。这包括在{{1}}中进行计算,忽略溢出并返回底层硬件返回的任何内容,格式化硬盘,让你的猫怀孕,或介于两者之间。

大多数编译器可能会在大多数情况下忽略它,并使用“overflow is UB”来优化代码,其余时间会大幅增加。 SO上有一个很好的例子:Why does integer overflow on x86 with GCC cause an infinite loop?