b = (a) + (++a);
これには未定義の動作があります。
C99 標準 (実際にはN1256 ドラフト)、6.5p2 を引用します。
前のシーケンス ポイントと次のシーケンス ポイントの間で、オブジェクトの格納値は、式の評価によって最大 1 回変更されます。さらに、以前の値は、保存する値を決定するためにのみ読み取られます。
この式は の値の読み取りa
と更新の両方を行います。読み取り操作 ( の左辺+
) は、書き込み操作 ( の右辺) によって格納される値を決定するために使用されません+
。
2011 ISO C 規格 ( N1570 ドラフトから引用) では、これは別の方法で述べられていますが、本質的には同じ意味です。
スカラー オブジェクトに対する副作用が、同じスカラー オブジェクトに対する別の副作用または同じスカラー オブジェクトの値を使用した値の計算と比較してシーケンス化されていない場合、動作は未定義です。式の部分式に複数の順序付けが許可されている場合、いずれかの順序付けでそのような順序付けされていない副作用が発生した場合の動作は未定義です。
(a)
の値を使用した値の計算ですa
。(a++)
の副作用a
です。のオペランドの評価順序が+
指定されていないため、これら 2 つの演算は相互に順不同です。
したがって、評価の順序が定義されていないだけの問題ではありません。動作は定義されておらず、演算子のオペランドが+
2 つの可能な順序のいずれかで評価される可能性に限定されません。
いいえ、括弧はこれを変更しません。
これについては、 comp.lang.c FAQのセクション 3 で詳しく説明されています。