【问题标题】:When does C++11 do arithmetic type conversions relative to operator precedence?C++11什么时候做相对于运算符优先级的算术类型转换?
【发布时间】:2019-01-09 22:10:51
【问题描述】:

如果我有以下代码:

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

C++11 语言如何指定执行乘法?例如,val1val2val3 是否根据运算符优先级乘以 32 位整数,可能溢出,然后转换为双精度数,还是将它们相乘为双精度数?

一般来说,该标准在这个主题上到底说了些什么?它在 C++ 的后续版本(例如 C++17)中是否发生了变化?

【问题讨论】:

  • 运算符优先级意味着在这种情况下,乘法发生在加法之前。表达式val2*val3*val4 计算为int32_t - 也有溢出的任何影响。然后将其结果转换为double,然后再添加到val1。 C++11 之前的所有 C++ 版本都具有相同的功能。固定宽度类型,如 int32_t,在 C++11 之前不是标准的。
  • 您首先使用的是双精度值,因此当它们影响双精度值时,所有期望的结果都会变成双精度值,并且会发生转化。从左到右val1+((val2*val3)*val4)

标签: c++ c++11 floating-point type-conversion integer-overflow


【解决方案1】:

表达式

val1 + val2 * val3 * val4

具有double 的类型,但乘法部分的类型为int32_t。如果我们应用关于如何评估它的规则,我们有

val1 + (val2 * val3 * val4)

因为乘法具有更高的优先级,它将在不考虑val1 的类型的情况下进行计算,并且由于所有操作数具有相同的类型,因此结果类型将与操作数相同。然后将该结果转换为double 并添加到val1。这种行为在任何 C++ 版本中都没有改变。

要使乘法以double 发生,您需要将val2val3 转换为双精度数,这将使整个乘法部分评估为double。看起来像

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

括号不是必需的,但我喜欢用它们来显示分组

【讨论】:

  • 完成同样事情的更简洁的方法是val1 + (1.0 * val2 * val3 * val4)
  • @dan04 简洁但不明确。下一个阅读代码的人可能太聪明了,删除了1.0 *,因为它似乎不会影响结果,而删除static_cast 的人只会得到他们应得的;)
猜你喜欢
  • 2017-11-01
  • 2023-02-09
  • 2019-06-06
  • 2014-06-03
  • 2012-05-04
  • 2015-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多