请考虑以下代码:
#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.将main
的第二行更改为double x = 1.0/0.0;
会产生预期的行为。这是允许的,还是一个bug?
编辑:对于它的价值,起初似乎在大多数现实世界的代码中,可能导致引发fenv异常的操作无法优化,因此可以安全地执行大型计算并在结束时检查是否发生了溢出,被零除等。但是,当您考虑内联和优化时,事情会变得混乱,并且会出现真正的问题。如果这样的函数在由于常量参数总是最终除以零的情况下被内联,gcc可能会非常智能并且基本上优化整个内联函数return INFINITY;
而不提高任何例外。
答案 0 :(得分:6)
这是预期的行为。 gcc不会对表达式求值,因为之后它与它无关。
如果使用“-Wall”进行编译,它会警告您该语句无效,并且它会忽略该pragma语句。
GCC不完全符合C99标准。有关更多信息,请参阅: http://gcc.gnu.org/c99status.html
有关实施此行为的问题,请参阅:http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20785
答案 1 :(得分:2)
这是一个灰色地带。严格阅读标准的浮点环境部分很容易让人相信这是一个错误。但我怀疑GCC维护者不同意这种阅读。
就此而言,我不确定GCC是否声称理解FENV_ACCESS编译指示。当然早期的版本没有。
答案 2 :(得分:2)
在gcc 4.6.0上使用-Wall
进行编译说:
f.c:5:0: warning: ignoring #pragma FENV_ACCESS ON [-Wunknown-pragmas]
* `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邮件列表。
答案 3 :(得分:0)
您的编译器可能已优化原始版本。认识到这两个常量在任何非平凡的意义上都没有被“使用”,它甚至可能不存在于已编译的二进制文件中。
第二个例子通过将操作实际分配给变量来改变它。
答案 4 :(得分:0)
我认为表达式在第一种情况下被优化掉了,但在第二种情况下却没有。我可以使用gcc 4.2和gcc -O0
重现您的搜索结果,但是如果我转到gcc -O3
那么我在两种情况下都会得到0。