2

GCC(私にとっては4.0)を使用すると、これは合法です:

if(__builtin_expect(setjmp(buf) != 0, 1))
  {
    // handle error
  }
else
  {
    // do action
  }

2003 年に GCC で問題が発生したという議論を見つけましたが、今では修正されていると思います。setjmpC 標準では、次の 4 つの条件のいずれかである場合を除き、使用は違法であると規定されています。

  • 関係演算子または等値演算子の 1 つのオペランドと、他のオペランドが整数定数式であり、結果の式が選択ステートメントまたは反復ステートメントの制御式全体になります。

しかし、これが GCC 拡張機能である場合、GCC で動作することを保証できますか? 既に非標準の機能であるためです。私はそれをテストし、実際にそれを破るためにどれだけのテストをしなければならないかわかりませんが、うまくいくように見えました. __builtin_expect(非 GCC の no-op として定義されているマクロの背後に呼び出しを隠しているため、他のコンパイラでは完全に合法です。)

4

2 に答える 2

0

標準が話していたのは、次のようなことを説明することだったと思います:

int x = printf("howdy");
if (setjmp(buf) != x ) {
    function_that_might_call_longjmp_with_x(buf, x);
} else {
    do_something_about_them_errors();
}

xこの場合、前の行で割り当てられた値を持つことに頼ることはできません。コンパイラーが以前の場所を移動した可能性がありx(以前のレジスターを再利用するか、何かを使用)、比較を行ったコードが間違った場所を検索することになります。x(別の変数に保存してからx、関数を呼び出す前に別のものに再割り当てすることができます。これにより、問題がより明白になる可能性があります)

コードでは、次のように記述できます。

int conditional;
conditional = setjump(buf) != 0 ;
if(__builtin_expect( conditional, 1)) {
    // handle error
} else {
    // do action
}

そして、変数を代入するコード行がconditionalその要件を満たしていることに満足できると思います。

于 2011-01-07T02:16:42.133 に答える
0

しかし、これが GCC 拡張機能である場合、GCC で動作することを保証できますか? 既に非標準の機能であるためです。私はそれをテストし、実際にそれを破るためにどれだけのテストをしなければならないかわかりませんが、うまくいくように見えました. (私は __builtin_expect への呼び出しをマクロの背後に隠しています。これは、非 GCC の no-op として定義されているため、他のコンパイラでは完全に合法です。)

あなたは正しいです、 __builtin_expect は他のコンパイラのマクロ no-op である必要があるため、結果はまだ定義されています。

于 2011-01-07T02:35:34.650 に答える