简体   繁体   English

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

[英]When multiplying two integers and storing the result in a floating point variable, can the result flow over?

I've always been wondering how code like this actually works: 我一直想知道这样的代码实际上是如何工作的:

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

What if the integers are so large that a*b is larger than the maximum value that can be stored in a variable of the integer type. 如果整数太大以致a*b大于可以存储在整数类型变量中的最大值,那a*b怎么办? Will the compiler notice that the target type can hold larger values and convert the values to double first, or will the multiplication just flow over / wrap around? 编译器会注意到目标类型可以容纳更大的值并将值转换为double ,或者乘法是否会流过/回绕?

When multiplying two integer values, the compiler will never by itself convert the result to a floating point type. 当乘以两个整数值时,编译器本身永远不会将结果转换为浮点类型。 That is, if you multiply two int values, the result too will be an int value. 也就是说,如果将两个int值相乘,结果也将是一个int值。

So, what you're code is effectively doing is: 那么,你的代码有效的是:

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

Thus, the result would only overflow if it cannot be stored within an int. 因此,只有在无法存储在int中时,结果才会溢出。 The conversion and assignment to a double is done only after the result is calculated. 只有在计算结果后才能转换和赋值给double

The answer is no. 答案是不。 The compiler will not convert the integers to doubles because the compiler doesn't run any code. 编译器不会将整数转换为双精度,因为编译器不运行任何代码。 When the program executes, the integers will be multiplied together (and maybe overflow) and that result will be stored in 'c', but the fact that 'c' is a double only means it's large enough to hold the result. 当程序执行时,整数将被乘法(并且可能溢出)并且结果将存储在'c'中,但'c'仅为双精度的事实意味着它足够大以保持结果。 The overflow would have already happened before being placed in 'c'. 溢出在放入'c'之前就已经发生了。

If the compiler was capable of changing the data types, it would mean the compiler could not only affect your final program size by changing data types, but also mess up data type expectations in other portions of your code. 如果编译器能够更改数据类型,则意味着编译器不仅可以通过更改数据类型来影响最终的程序大小,还会在代码的其他部分中弄乱数据类型期望。 Bad things could happen, for example, if you were expecting to bit-shift an integer, but at run-time you are bit shifting a double because the compiler decided to change your data type. 例如,如果您希望对一个整数进行位移,可能会发生不好的事情,但是在运行时,由于编译器决定更改您的数据类型,因此您需要进行双位移位。 The horrors! 恐怖!

The result of a multiplication will be determined by the usual arithmetic conversions and will only take into considerations the operands of the multiplication itself, from the draft C++ standard: 乘法的结果将由通常的算术转换确定,并且只考虑乘法本身的操作数,来自草案C ++标准:

The operands of * and / shall have arithmetic or unscoped enumeration type; *和/的操作数应具有算术或未范围的枚举类型; the operands of % shall have integral or unscoped enumeration type. %的操作数应具有整数或无范围的枚举类型。 The usual arithmetic conversions are performed on the operands and determine the type of the result. 通常的算术转换是在操作数上执行的,并确定结果的类型。

If the results can not be represented by the converted type then it will invoke undefined behavior: 如果结果不能由转换后的类型表示,那么它将调用未定义的行为:

If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined 如果在评估表达式期间,结果未在数学上定义或未在其类型的可表示值范围内,则行为未定义

so you should detected overflow before the operation and deal accordingly, see Will gcc skip this check for signed integer overflow? 所以你应该在操作之前检测到溢出并相应地处理,请参阅gcc会跳过此检查是否有符号整数溢出?

What if the integers are so large that a*b is larger than the maximum value that can be stored in a variable of the integer type. 如果整数太大以致a*b大于可以存储在整数类型变量中的最大值,那a*b怎么办?

Signed integer overflow is undefined behavior. 有符号整数溢出是未定义的行为。

Will the compiler notice that the target type can hold larger values and convert the values to double first, or will the multiplication just flow over / wrap around? 编译器会注意到目标类型可以容纳更大的值并将值转换为double ,或者乘法是否会流过/回绕?

Since it's undefined, the compiler is allowed to do anything. 由于它未定义,因此允许编译器执行任何操作。 That includes doing the computation in double , ignoring the overflow and returning whatever the underlying hardware returns, formatting your hard drive, making your cat pregnant, or anything in between. 这包括以double计算,忽略溢出并返回底层硬件返回的任何内容,格式化硬盘,让你的猫怀孕,或介于两者之间。

Most compilers would probably ignore it most of the time, and use "overflow is UB" to optimize your code the rest of the time, which then blows up spectacularly. 大多数编译器可能在大多数情况下都会忽略它,并使用“overflow is UB”来优化代码,其余的时间会大大加剧。 There's a nice example on SO: Why does integer overflow on x86 with GCC cause an infinite loop? 在SO上有一个很好的例子: 为什么带有GCC的x86上的整数溢出会导致无限循环?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM