質問: --n / --n; cout << n << endl; ``` と書いてありました。 これを実際に実行してみると1と表示され、確かに予想していなかった結果でした。 ただ、これは評価順序が不定だからという理由では納得できません。 何故なら左から評価すれば、 ``` n=0/-1 ``` なので、0。 右から評価すれば ``` n=-1/0 ``` で0で除算する事になりエラーとなり、 評価順序がどちらの場合も1にはならないように思えるからです。 何故1になるのでしょうか? 「同じ数/同じ数」という形で評価されて1となっていると仮定すると、 同時に評価されていると考える事できますが、 そのような事はあるのでしょうか?
回答: > > これは評価順序が不定だからという理由では納得できません。 > > > 直接原因は、式`n = --n / --n;`の評価順序が不定なことにより「未定義の動作(Undefined Behavior)」が生じるためです。 プログラミング言語CやC++では「未定義の動作」に対して、何の保証も与えなくて良いという仕様になっています。質問中の例で言えば、値`0`となることもゼロ除算となることも、値`1`となることも、全てがこの式の実行に対する正しい結末と言えます。(もちろん、プログラマ視点では納得いかないでしょうけど...) > > 「同じ数/同じ数」という形で評価されて1となっていると仮定すると、同時に評価されていると考える事できますが、そのような事はあるのでしょうか? > > > ありえます。C++コンパイラはあるコードが「未定義の動作」を起こしうる場合、"そのような未定義の動作は起こるはずがない"と解釈してコード最適化を行います。これは良い意味では、プログラマが間違ったコードを書くはずがないという前提に立って、最大限の最適化を行うと解釈できます。ただし、ひとたび間違った=未定義の動作を含むコードに対しては、プログラマにとって予期しない結果をもたらすことがあります。 以下は、(日本語)関連記事へのリンクです: * EXP30-C. 副作用が発生する式の評価順序に依存しない, MSC15-C. 未定義の動作に依存しない * 全てのCプログラマが未定義な振る舞いについて知っておくべきこと * Old New Thing: 未定義動作はタイムトラベルを引き起こす(他にもいろいろあるけど、タイムトラベルが一番ぶっ飛んでる)