web-dev-qa-db-ja.com

-fwrapvは何をしますか?

Fwrapvを使用してコンパイルした場合と使用しない場合で動作が異なるコード例を誰かが提供できますか?.

-fwrapvは、「加算、減算、乗算の符号付き算術オーバーフローを想定し、2の補数表現を使用してラップする」と述べています。

しかし、オーバーフローしようとすると、fwrapvの有無にかかわらず結果は同じになります。

14
ktal

この関数について考えてみてください。

int f(int i) {
    return i+1 > i;
}

数学的に言えば、i+1は、任意の整数iに対して常にiより大きくなければなりません。ただし、32ビットのintの場合、そのステートメントをfalseにするiの値が1つあります。これは、2147483647(つまり、0x7FFFFFFF、つまりINT_MAX)です。その数に1を追加するとオーバーフローが発生し、2の補数表現によると、新しい値はwrap-aroundになり、-2147483648になります。したがって、i+1>1-2147483648>2147483647になりますが、これは誤りです。

-fwrapvなしでコンパイルすると、コンパイラはオーバーフローが「非ラップ」であると見なし、関数を最適化して、常に1を返します(オーバーフローの場合は無視します)。

with -fwrapvをコンパイルすると、関数は最適化されませんになり、オーバーフローが「ラッピング」になるため、1を加算して2つの値を比較するロジックがあります。 (つまり、オーバーフローした数値は2の補数表現に従って折り返されます)。

違いは、右側のペインの 生成されたアセンブリ -で簡単に確認できます。-fwrapvがない場合、関数は常に1true)を返します。

8
Aziz
for (int i=0; i>=0; i++)
    printf("%d\n", i);

-fwrapvを使用すると、ループはINT_MAXの反復後に終了します。 iの値がi++の場合、INT_MAXの評価によって未定義の動作が無条件に呼び出されるため、これがないと何でもできます。実際には、最適化コンパイラはループ条件を省略し、無限ループを生成する可能性があります。

5
R..

ISO標準ワーキンググループWG14は、すべてのCコンパイラが準拠しなければならない規則を確立するために存在します。一部のコンパイラは、拡張機能も実装する場合があります(実際に実装します)。 ISO標準Cによると、これらの拡張機能は次のいずれかと見なされます。

  • implementation-defined、つまり、コンパイラ開発者は、準拠したC実装と見なされるために、選択を行い、その選択を文書化し、ロットを維持する必要があります。
  • C11/3.4.3は未定義の振る舞いの定義を確立し、非常に馴染みのある を示します。私が書くことができるものよりもはるかに優れています:

    1未定義の振る舞い動作、移植不可能または誤ったプログラム構成または誤ったデータの使用時。この国際規格は要件を課していません

    2注考えられる未定義の動作は、予測できない結果で状況を完全に無視することから、環境に特徴的な文書化された方法で翻訳またはプログラムの実行中に動作すること(診断メッセージの発行の有無にかかわらず)、翻訳または実行の終了(診断メッセージの発行)。

    3例未定義の動作の例は、整数オーバーフローの動作です。


不特定の動作もありますが、標準でそれについて読むための演習として残しておきます。

踏む場所に注意してください。これは、一般的に受け入れられている一般的に受け入れられている未定義の動作の1つであり、トラップの表現なしで2の補数表現でLIAスタイルのラッピングが発生すると通常予想されます。すべて1を含むビット表現に対応するトラップ表現を使用する実装があることを理解することが重要です。

要約すると、fwrapvftrapvは、開発者があなたに代わって行わなければならなかった選択をあなたに渡すために存在し、その選択は、符号付き整数オーバーフロー時に起こることです。発生します。もちろん、デフォルトを選択する必要があります。これは、あなたの場合、fwrapvではなくftrapvに相関しているように見えます。そうである必要はなく、これらのコンパイラオプション何かを変更する場合でもありません。これまで。

2
autistic