简体   繁体   中英

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. 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?

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.

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. The conversion and assignment to a double is done only after the result is calculated.

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. The overflow would have already happened before being placed in '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:

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?

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.

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?

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.

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. There's a nice example on SO: Why does integer overflow on x86 with GCC cause an infinite loop?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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