7

未定義の動作とシーケンス ポイントに関するこのSO C++ FAQを読み、少し実験しました。次のコードgcc-4.5.2では、コード コメントで言及されている行でのみ警告が表示されますが、その前の 1 行も未定義の動作を示していますね。加算のどのオペランドが最初に実行されるかはわかりません (+シーケンス ポイントがないため)。gcc がこの行でも警告を表示しないのはなぜですか?

int i=0;
int j=0;

int foo(void) {
    i=1;
    return i;
}

int main(void) {
    i = i + foo(); 
    j = j + (j=1); //Here is a rightly warning
    return 0;
}

助けてくれてありがとう。

4

3 に答える 3

17

i = i + foo(); の振る舞い 未指定ですが、未定義ではありません。未定義は、プログラムを中止する場合でも、可能な動作が許可されることを意味します。未指定は、i が最初に評価されるか、または foo() のいずれかを意味します。はい、foo は同じ i に書き込みますが、別のステートメントで発生するため、そのストアの前後にシーケンス ポイントがあります。

于 2011-11-26T10:24:03.603 に答える
2

プログラムの行i = i + foo();は指定されていませんが、未定義ではありません。

コンパイラは、誤検知なしで (コンパイラが警告するたびに、プログラマーが修正すべき欠陥がある)、または少なくとも非常に低い誤検知率で警告を発行しようとします。これは、その代わりに、かなりの数の偽陰性があることを意味します。同じ哲学に沿って、コンパイラは通常、未指定の動作について警告しません。

プログラムに関する警告を得るには、警告に対してより積極的な静的アナライザーを調べる必要がありますが、誤検出がわずかに多くなります。静的アナライザーは、未指定の動作について警告することを非常にうまく決定できます。それらのいくつかは、定義されているとはいえ、プログラマーがおそらく混乱していたことを示す定義済みの動作について警告することさえあります。

于 2011-11-26T11:39:55.160 に答える
-6

foo() を呼び出すと i が変更されることは人間にはわかりますが、コンピューター プログラムの場合はわかりにくいです。これを見るように設計されていません。

于 2011-11-26T10:26:18.620 に答える