2

このコードには興味深いバグがあります:

some_struct struct_array1[10] = {0};
some_struct struct_array2[10] = {0}
int i;

for (i = 0; 
     i < sizeof(struct_array1) / sizeof(struct_array1[0]); 
     struct_array1[i].value = struct_array2[i++].value = 1)
    ;

ほとんどのコンパイラでは、上記のコードにより、それぞれの配列内のすべての構造体の「値」フィールドが 1 に設定されます。ただし、ある特定のコンパイラ (xcc と呼びましょう) では、struct_array1 の構造体が正しく初期化されません。「値」フィールドはすべての構造体で 0 に設定されていますが、これにはちょっと驚きました。

次のコード スニペットは、すべてのコンパイラで期待どおりに機能します。

for (i = 0; 
     i < sizeof(struct_array1) / sizeof(struct_array1[0]); 
     i++)
{
    struct_array1[i].value = struct_array2[i].value = 1;
}

さて、私は完全にここから離れていますか、それとも問題のあるコンパイラ「xcc」が単にバグを表示しているだけなのでしょうか?

最初のコード スニペットで実装固有の動作を示すものは見つかりません。私が理解していることから、後置インクリメントは割り当てよりも優先され、割り当ては右から左に評価されるべきです。最初のコード スニペットは、少し読みにくいことを除けば、おかしなことは何もないはずです。

4

3 に答える 3

8

未定義の動作を呼び出しました。これはi、シーケンスポイントを介さずに、新しい値の計算以外の目的で値を変更およびフェッチするためです。

C99標準の関連部分は、セクション6.5の次の条項です。

前のシーケンスポイントと次のシーケンスポイントの間で、オブジェクトは、式の評価によって、格納されている値を最大で1回変更する必要があります。さらに、前の値は、格納される値を決定するためにのみ読み取られるものとします。

于 2010-03-03T12:01:27.983 に答える
5

struct_array1[i].value = struct_array2[i++].value = 1

i++次のシーケンスポイントに到達するまで、すべての副作用を完了することが保証されていないため、これは未定義の動作だと思います。次のシーケンス ポイントは;、ステートメントの末尾にある「虚数」です。これはよくある落とし穴です。シーケンス ポイントを検索するだけで、それに関連する SO に関する多くのトピックを見つけることができると思います。

于 2010-03-03T11:57:00.927 に答える
0

実際には、signleで、同じ変数に対して複数の評価を実行することは想定されていません。

表現 。そのようなことをすると、それは未定義の振る舞いになります。

于 2010-03-03T12:02:03.450 に答える