I recently faced a problem on a C++ code of mine making me wonder whether I had some misunderstanding of what the compiler would do with long operations... Just look at the following code:
#include <iostream>
int main() {
int i = 1024, j = 1024, k = 1024, n = 3;
long long l = 5;
std::cout << i * j * k * n * l << std::endl; // #1
std::cout << ( i * j * k * n ) * l << std::endl; // #2
std::cout << l * i * j * k * n << std::endl; // #3
return 0;
}
For me the order in which the multiplications will happen in any of these 3 lines is undefined. However, here is what I thought would happen (assuming int
is 32b, long long
is 64b and they both follow the IEEE rules):
int
s as intermediate results, leading to an overflow and to store -1073741824. This intermediate result is promoted to long long
for the last multiplication and the printed result should therefore be -5368709120.Now, for lines #1 and #3 here is were I'm unsure: I thought that although the order of evaluation was undefined, the compiler would "promote" all operations to the type of the largest operand, namely long long
here. Therefore, no overflow would happen in this case since all computations would be made in 64b... But this is what GCC 5.3.0 gives me for this code:
~/tmp$ g++-5 cast.cc
~/tmp$ ./a.out
-5368709120
-5368709120
16106127360
I would have expected 16106127360 for the first result too. Since I doubt there is a compiler bug of this magnitude in GCC, I guess the bug lies between the keyboard and the chair.
Could anyone please confirm / infirm this is undefined behaviour and GCC is correct in giving me whatever it gives (since this is undefined)?
GCC is correct.
For example, first expression is parsed as i * j * k * n * l = ((((i * j) * k) * n) * l)
and the promotion happens only when last of multiplications is computed, but at this moment left operand is already incorrect.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With