全体として、ステートメント:
print(x, x++);
未定義動作になります。プログラムが未定義の動作をすると、それは有効なC ++プログラムではなくなり、文字通りどのような動作も可能になります。したがって、そのようなプログラムの理由を見つけることは無意味です。
なぜこの未定義動作なのですか?
プログラムを段階的に評価して、それが未定義動作を引き起こすことを疑いの余地なく証明できるところまで見ていきましょう。
関数への引数の評価の順序は指定されていません[参照1]。
不特定とは、実装がこの特定の機能を必要に応じて実装できることを意味し、その詳細を文書化する必要はありません。
上記のルールを関数呼び出しに適用します。
print(x, x++);
実装はこれを次のように評価する可能性があります。
- 左から右または
- 右から左または
- 任意の魔法の順序(3つ以上の関数の引数の場合)
つまり、C ++標準に従って実装する必要がないため、特定の順序に従う実装に依存することはできません。
C / C ++では、シーケンスポイントが介在しない限り、変数の読み取りまたは書き込みを2回以上行うことはできません[参照2]。そうすると、未定義動作が発生します。いずれかの引数が前述の関数で最初に評価されるかどうかは関係ありません。 、それらの間にシーケンスポイントはありません。シーケンスポイントは、すべての関数引数の評価後にのみ存在します[参照3]。
この場合x
、介在するシーケンスポイントなしでアクセスされているため、未定義の動作が発生します。
簡単に言えば、そのような未定義動作を呼び出さないコードを書くのが最善です。そうすると、そのようなプログラムから特定の動作を期待することができないからです。
[参照1] C++ 03標準§5.2.2.8
パラ8:
[...]関数の引数の評価の順序は指定されていません。[...]
[参照2] C++ 03 5式[expr]:
パラ4:
....
前のシーケンスポイントと次のシーケンスポイントの間で、スカラーオブジェクトは、式の評価によって、格納されている値を最大で1回変更する必要があります。さらに、前の値は、保存される値を決定するためにのみアクセスされるものとします。この段落の要件は、完全な式の部分式の許容される順序ごとに満たされるものとします。それ以外の場合、動作は未定義です。
[参照3] C++ 03 1.9プログラムの実行[intro.execution]:
パラ17:
関数を呼び出す場合(関数がインラインであるかどうかに関係なく)、すべての関数の引数(存在する場合)の評価後、関数本体の式またはステートメントの実行前に実行されるシーケンスポイントがあります。