93

私は次のコードを持っています:

#include <stdio.h>
int main(int argc, char **argv) {
    int i = 0;
    (i+=10)+=10;
    printf("i = %d\n", i);
    return 0;
}

gcc を使用して C ソースとしてコンパイルしようとすると、エラーが発生します。

error: lvalue required as left operand of assignment

しかし、g++ を使用して C++ ソースとしてコンパイルすると、エラーは発生せず、実行可能ファイルを実行すると、次のようになります。

i = 20

なぜ異なる動作ですか?

4

2 に答える 2

134

複合代入演算子のセマンティクスは、C と C++ で異なります。

C99 標準、6.5.16、パート 3:

代入演算子は、左オペランドで指定されたオブジェクトに値を格納します。代入式は、代入後に左オペランドの値を持ちますが、左辺値ではありません。

C++ 5.17.1 の場合:

代入演算子 (=) と複合代入演算子はすべて右から左にグループ化されます。すべてが左オペランドとして変更可能な左辺値を必要とし、代入が行われた後、左オペランドの型と値を持つ左辺値を返します。

EDIT : C++での の動作は(i+=10)+=10C++98 では定義されていませんが、C++11 では明確に定義されています。標準の関連部分については、NPEによる質問に対するこの回答を参照してください。

于 2012-05-18T13:57:58.457 に答える
51

無効な C コードであることに加えて、行

(i+=10)+=10;

iシーケンス ポイント間で 2 回変更されるため、C と C++03 の両方で未定義の動作が発生します。

C++ でのコンパイルが許可されている理由については、次のとおりです。

[C++N3242 5.17.1] 代入演算子 (=) と複合代入演算子はすべて右から左にグループ化されます。すべてが左オペランドとして変更可能な左辺値を必要とし、左オペランドを参照する左辺値を返します。

同じ段落は次のように続けています。

いずれの場合も、代入は、右オペランドと左オペランドの値の計算の後、代入式の値の計算の前に順序付けされます。

これは、C++11 では、式が未定義の動作をしなくなったことを示唆しています。

于 2012-05-18T13:56:06.507 に答える