以下のコードの場合:
main() {
int i = 1 ;
cout << i << ++i << i++ ;
}
出力が 122 ではなく 331 になるのはなぜですか?
printf
( cout の代わりに使っても同じですか?)
以下のコードの場合:
main() {
int i = 1 ;
cout << i << ++i << i++ ;
}
出力が 122 ではなく 331 になるのはなぜですか?
printf
( cout の代わりに使っても同じですか?)
<<
は関数、つまり のようなものostream& operator<<(ostream& lhs, RhsType rhs)
です。
cout << a;
と同等です
operator<<(cout, a);
この関数は lhs を返します。つまりreturn lhs
、上記の例cout
では が返されます。
だからあなたの例
cout << i << ++i << i++ ;
と同等です
operator<<(operator<<(operator<<(cout, i), ++i), i++);
訂正C++ は、インクリメント操作が実行される順序を指定しません。あなたと私には、最もネストされたものが最初になるのは論理的に思えますが、コンパイラに関する限り、好きなときにインクリメントを自由に実行できます。myFunc(cout, i++, ++i, i)
インクリメントが評価される順序が定義されていない関数のような動作と同じです。保証されている唯一のことは、関数が内部から外部に評価されることです。
コンパイラは、評価の順序を自由に変更できます。同じステートメントで i を複数回変更しているため、未定義の動作が発生します。
これが、そのようなコードを書くべきではない理由です。これにより、異なるコンパイラで異なる結果が得られると確信しています。Visual C++ を使用すると、デバッグ バージョンとリリース バージョンで実行すると、異なる出力が得られます。
観察した出力は、次のように説明できます。式は、出力に渡される前に、または出力のために右から左に評価されます。cout
printf
開始値は 1 です
i++ はポストインクリメントです。つまり、値 (1) を出力してから 2 にインクリメントします: 出力 1
++i はプリインクリメンなので、出力される前に 2 は 3 になります: 出力 3
最後に、i (3) の現在の値が出力されます: 出力 3
これらのそれぞれの値は、出力ルーチンに渡されます。
明確にするために、私の答えは、観察された動作を説明しようとするだけであり、コンパイラまたは出力ルーチンが評価/アクションを順序付ける方法に関する厳密で迅速な規則を定めていません。
そうは言っても、このタイプのコードは良い習慣ではなく、回避できるあらゆる種類の問題を引き起こす可能性が非常に高いです。