5

考虑以下代码:

#include <fenv.h>
#include <stdio.h>
int main()
{
    #pragma STDC FENV_ACCESS ON
    1.0/0.0;
    printf("%x\n", fetestexcept(FE_ALL_EXCEPT));
}

我希望它打印一个对应于 的非零值FE_DIVBYZERO,但它打印 0。更改 to 的第二行maindouble x = 1.0/0.0;给出预期的行为。这是允许的,还是一个错误?

编辑:对于它的价值,起初似乎在大多数现实世界的代码中,可能导致 fenv 异常的操作无法被优化出来,因此人们可以安全地执行大型计算并在最后检查是否有发生溢出、除零等。然而,当你考虑内联和优化时,事情变得一团糟,一个真正的问题出现了。如果这样的函数在由于常量参数而总是被零除的情况下被内联,gcc 可能会变得非常聪明,并从本质上优化整个内联函数而return INFINITY;不会引发任何异常。

4

5 回答 5

6

这是预期的行为。gcc 不计算表达式,因为之后它与它无关。

如果您使用“-Wall”进行编译,它会警告您该语句无效,并且它会忽略 pragma 语句。

GCC 不完全符合 C99。有关详细信息,请参阅: http: //gcc.gnu.org/c99status.html

有关实现此行为的问题,请参阅:http ://gcc.gnu.org/bugzilla/show_bug.cgi?id=20785

于 2011-06-13T21:56:41.730 回答
2

这是一个灰色地带。严格阅读标准的浮点环境部分很容易让人相信这是一个错误。然而,我怀疑 GCC 的维护者会不同意这种解读。

就此而言,我不确定 GCC 甚至声称了解 FENV_ACCESS 杂注。当然早期版本没有。

于 2011-06-13T22:04:55.240 回答
2

在 gcc 4.6.0 上编译-Wall说:

f.c:5:0: warning: ignoring #pragma FENV_ACCESS ON [-Wunknown-pragmas]

根据GCC 信息页面

* `The default state for the `FENV_ACCESS' pragma (C99 7.6.1).'

 This pragma is not implemented, but the default is to "off" unless
 `-frounding-math' is used in which case it is "on".

不幸的是,-frounding-math似乎对您的程序没有任何影响。

可以说是编译器错误;我会在 GCC 邮件列表之一上询问。

于 2011-06-13T22:06:12.333 回答
0

您的编译器可能已经优化了原始版本。认识到这两个常量在任何非平凡意义上都没有“使用”,它甚至可能不存在于编译的二进制文件中。

第二个示例通过将操作实际分配给变量来改变这一点。

于 2011-06-13T21:52:10.947 回答
0

我认为表达式在第一种情况下得到优化,但不是在第二种情况下。我可以用 gcc 4.2 with 重现你的结果gcc -O0,但如果我去,gcc -O3那么在这两种情况下我都会得到 0。

于 2011-06-13T21:54:39.887 回答