§5.2.6/1から(強調は私のものです):
後置 ++ 式の値は、そのオペランドの値です。[ 注: 得られた値は元の値のコピーです — 末尾の注 ] オペランドは変更可能な左辺値でなければなりません。オペランドの型は、cv bool 以外の算術型、または完全なオブジェクト型へのポインターでなければなりません。オペランド オブジェクトの値は、それに 1 を追加することによって変更されます。++ 式の値の計算は、オペランド オブジェクトの変更の前に順序付けられます. 不定順序の関数呼び出しに関しては、後置 ++ の操作は単一の評価です。[ 注: したがって、関数呼び出しは、左辺値から右辺値への変換と、単一の後置 ++ 演算子に関連する副作用との間に介在してはなりません。— 終わりの注 ] 結果は prvalue です。結果の型は、オペランドの型の cv 非修飾バージョンです。オペランドがインクリメントされた値を表すことができないビットフィールドである場合、ビットフィールドの結果の値は実装定義です。[expr.add] と [expr.ass] も参照してください。
つまり、オペランド オブジェクトの変更は、式の値の計算の後++
に順序付けられます。
§5.18/1から(強調は私のものです):
代入演算子 (=) と複合代入演算子はすべて右から左にグループ化されます。すべてが左オペランドとして変更可能な左辺値を必要とし、左オペランドを参照する左辺値を返します。左オペランドがビットフィールドの場合、結果は常にビットフィールドになります。いずれの場合も、代入は、右オペランドと左オペランドの値の計算の後、代入式の値の計算の前に順序付けられます。不定順序の関数呼び出しに関しては、複合代入の操作は単一の評価です。[ 注: したがって、関数呼び出しは、左辺値から右辺値への変換と、単一の複合代入演算子に関連する副作用との間に介在してはなりません。— エンドノート]
代入式:
条件式
論理和式 代入演算子 初期化句
スロー式代入演算子:
= *= /= %= += -= >>= <<= &= ^= |=のいずれか
代入は、代入演算子の左右のオペランドの値計算の後にも順序付けされます。
ということで、式を考えると
i = i++;
§5.2.6/1 からi++
、この代入式の RHS に対する式 の副作用は、 の値計算の後に続くことがわかりi++
ます。また、§5.18/1 から、代入演算子の LHS への代入に対応する副作用i
は、代入演算子の右オペランドと左オペランドの値計算の後に並べられることがわかります。
i = i++;
しかし、式が未定義の動作を示すことを証明するために、これら 2 つの副作用がシーケンス化されていないことをどのように示すのでしょうか?