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));
}

に対応するゼロ以外の値を出力することを期待しますが、0 をFE_DIVBYZERO出力します。 の 2 行目を に変更するとmaindouble x = 1.0/0.0;期待される動作が得られます。これは許可されていますか、それともバグですか?

編集:最初は、ほとんどの実際のコードでは、fenv 例外が発生する可能性のある操作を最適化できなかったように見えるかもしれません。そのため、大規模な計算を安全に実行し、最後にオーバーフロー、div-by-zero などが発生しました。ただし、インライン化と最適化を検討すると、事態が混乱し、実際の問題が発生します。そのような関数が、定数引数のために常にゼロで除算される状況でインライン化された場合、gcc は非常にスマートになり、インライン化された関数全体を本質的にreturn INFINITY;例外を発生させずに最適化する可能性があります。

4

5 に答える 5

6

これは予期される動作です。gcc は式を評価しません。後でそれとは何の関係もないからです。

「-Wall」を指定してコンパイルすると、ステートメントが無効であり、プラグマ ステートメントが無視されることが警告されます。

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

-Wallgcc 4.6.0でコンパイルすると、次のようになります。

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 メーリング リストの 1 つで質問します。

于 2011-06-13T22:06:12.333 に答える
0

コンパイラが元のバージョンを最適化した可能性があります。2 つの定数が自明ではない意味で「使用」されていないことを認識すると、コンパイルされたバイナリには存在しない可能性さえあります。

2 番目の例では、操作を実際に変数に割り当てることで、これを変更しています。

于 2011-06-13T21:52:10.947 に答える
0

最初のケースでは式が最適化されていると思いますが、2番目のケースではそうではありません。gcc 4.2 withgcc -O0で結果を再現できますが、その後に行くとgcc -O3、どちらの場合も 0 になります。

于 2011-06-13T21:54:39.887 に答える