【问题标题】:Visual studio compiler optimisation for type casting in C++用于 C++ 中类型转换的 Visual Studio 编译器优化
【发布时间】:2016-02-29 09:41:11
【问题描述】:

我在代码中有以下语句:

int a = (int)( (float)(b * 1000) / (float)c + .5f );

其中b 也是int, 而c 是一个unsigned int,具有一个恒定值(在我的测试运行中为 15)

该语句在一个 while 循环中,其中 b 在每次迭代中递增 1。

在我决定在 Visual Studio 中打开优化标志(最大化速度)之前,这段代码运行良好。之后,a 会随机发生溢出(即它的值为-2147483647)。在进一步调查时,这种溢出过去常常发生在 b 的不同值上。在我观察到的测试运行中,发生溢出的 b 值在 9-12 之间。

解决问题的方法是进行如下所示的小改动:

int a = (int)( (b * 1000.f) / c + .5f );

您对这有什么帮助有任何想法吗?它工作正常,但我不知道为什么?

编辑:根据 cmets 添加更多信息:

在记录时,我观察到:

(float)(b * 1000) / (float)c + .5f

被评估为一个非常大的 value ,当类型转换为 int 时导致溢出。但是,float(b*1000)float(c) 分别计算正确。

【问题讨论】:

  • b和c的类型有哪些?
  • @mustafagonul "其中b 也是intcunsigned int"
  • 您使用的优化标志很重要。该行为完全由实现定义。很明显,你犯了一个溢出错误。但我不知道,当您关闭优化标志时,它会以正确的方式运行。
  • 有没有可能,a 并没有真正溢出启用优化,只是调试器无法报告其真实值?除了调试器报告的值之外,您是否看到任何实际可验证的 a 不正确的证据?
  • 我正在使用 /O2 优化标志(最大化速度)

标签: c++ visual-studio compiler-optimization


【解决方案1】:

b * 1000 很可能会溢出int 类型;这样做的行为是未定义

删除所有那些令人困惑的演员表,并使用

b * 1000.0 / c + 0.5

相反。 1000.0double 字面量,并导致第一项以浮点数计算。

在转换回int 之前,您应该检查表达式的大小,尤其是在c 很小的情况下。 std::numeric_limits 对此很有用。

【讨论】:

  • 同样的问题,你如何解释 9-12 之间的 b 值溢出?
  • c 也在这里发挥作用。它的价值是什么?
  • 它没有,因为它在原始语句中被转换为float
  • 嗯,在将整个内容转换为int 时确实如此。这里有两个可能的溢出区域。
  • 对不起,当然,我误会了。 OP 提到 c 是 15。
【解决方案2】:

b * 1000int * int,所以会发生整数乘法,溢出风险较高。 (有符号整数算术溢出是未定义的行为

b 转换为float 也可以解决此问题。

int a = (int)( (float)b * 1000 / (float)c + .5f );

【讨论】:

  • 但我观察到低至 9 的值会溢出。9*1000 几乎不值得溢出。
  • 如果b 在 9-12 之间,你如何解释溢出? 9000-12000 不会溢出int
  • @TheBlueNotebook 你是什么意思? 9.9 无法存储到 int
  • 那不是小数点。这是一个句号。我会改写:但我观察到低至 9 的值会溢出 | 9*1000 几乎没有溢出价值。
猜你喜欢
  • 2012-02-09
  • 2011-04-13
  • 1970-01-01
  • 2010-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-19
相关资源
最近更新 更多