2

这是导致问题的程序的关键部分,并且程序是完全顺序的。

exist_是类bool私有成员,并且dbl_num_是类double私有成员

exist_ = false;
dbl_num_ = 0;
std::cout << dbl_num_ << " " ;
if(exist_ == true)
{
  dbl_num_ = 5;
}else
{
  dbl_num_ = NAN;
}

std::cout << exist_ << " " << dbl_num_ << std::endl;

使用选项 -ffast-math,我得到了打印输出“0 0 5”

没有选项 -ffast-math,我得到了打印输出“0 0 NAN”

此外,如果我将程序更改为

exist_ = false;
dbl_num_ = 0;
std::cout << dbl_num_ << " " ;
if(exist_ == true)
{
  std::cout << exist_ << " " ;
  dbl_num_ = 5;
}else
{
  dbl_num_ = NAN;
}

std::cout << exist_ << " " << dbl_num_ << std::endl;

使用选项-ffast-math,我得到“0 0 NAN”

比我将 NAN 更改为 -5

exist_ = false;
dbl_num_ = 0;
std::cout << dbl_num_ << " " ;
if(exist_ == true)
{
  dbl_num_ = 5;
}else
{
  dbl_num_ = -5;
}

std::cout << exist_ << " " << dbl_num_ << std::endl;

使用选项-ffast-math,我得到“0 0 -5”

我知道 -ffast-math 破坏了 IEEE 标准,并且它不检查 NAN,但它破坏上述简单条件检查的确切原因是什么?

4

1 回答 1

3

-ffast-math 指示 g++ 假设 NaN 永远不会出现。因此,将某些东西设置为 NaN 大致相当于未定义的行为,因为编译器可以安全地假设它永远不会发生。有关编译器如何消除它“知道”无法执行的分支以及如何令人惊讶的信息,请参阅这一系列 LLVM 博客文章。

简短版本:g++ 进入“我们处于快速数学模式,因此 dbl_num_ 永远不会设置为 NaN,因此永远不会采用 else 分支,因此存在必须为真,因此我可以优化除该路径之外的所有内容”。

编辑:另见这个gcc 错误报告。

于 2015-12-03T03:53:23.873 回答