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):
- For line #2, the parenthesis is evaluated first, using
int
s as intermediate results, leading to an overflow and to store -1073741824. This intermediate result is promoted tolong long
for the last multiplication and the printed result should therefore be -5368709120. - Lines #1 and #3 are "equivalent" since the order of evaluation is undefined.
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)?