2

If I have the following code:

double compute(double val1,
               int32_t val2,
               int32_t val3,
               int32_t val4) {
  return val1 + val2 * val3 * val4;
}

How does the C++11 language specify that the multiplication be performed? E.g., are val1, val2, and val3 multiplied as 32 bit integers, according to operator precedence, possibly overflowing, and then converted to a double, or are they multiplied as doubles?

In general, what exactly does the standard say on this subject? Has it changed in subsequent versions of C++ (e.g., C++17)?

WilliamKF
  • 41,123
  • 68
  • 193
  • 295
  • 3
    Operator precedence means that the multiplications occur, in this case, before the addition. The expression `val2*val3*val4` is calculated as a `int32_t` - with any effects of overflow as well. The result of that is then converted to `double` before addition to `val1`. All versions of C++ before C++11 have the same. Fixed-width types, like `int32_t`, were not standard before C++11. – Peter Jan 09 '19 at 22:17
  • https://stackoverflow.com/questions/30314291/operator-precedence-and-automatic-promotion-to-avoid-overflow – Martin Heralecký Jan 09 '19 at 22:18
  • fwiw [the overflow in action](https://wandbox.org/permlink/djiwK9nfSXP7PuVc) – 463035818_is_not_an_ai Jan 09 '19 at 22:21
  • You are using the double value in first place, so all of the desired result will become the double when they impact the double value and conversions will happen. From left to right `val1+((val2*val3)*val4)` – Nazari Jan 09 '19 at 22:27

1 Answers1

4

The expression

val1 + val2 * val3 * val4

has the type of double, but the multiplication part is of type int32_t. If we apply the rules on how it is evaluated we have

val1 + (val2 * val3 * val4)

because multiplication has a higher precedence, it will be evaluated without considering the type of val1 and since all of the operands have the same type the result type will be the same as the operands. That result is then converted to a double and added to val1. This behavior has not changed in any of the versions of C++.

To get the multiplication to happen as double you need to cast either val2 or val3 to a double, which will make the entire multiplication part evaluated as a double. That would look like

val1 + (static_cast<double>(val2) * val3 * val4)

the parentheses are not needed but I like using them to show the grouping

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • 1
    A terser way of accomplishing the same thing is `val1 + (1.0 * val2 * val3 * val4)`. – dan04 Jan 10 '19 at 00:55
  • @dan04 terse but not explicit. The next one reading the code might be too clever and remove the `1.0 *` because it seems like not effecting the result, while someone removing a `static_cast` will just get what they deserve ;) – 463035818_is_not_an_ai Jan 11 '19 at 09:49