exp777.hatenablog.com

頭の中はゲームでいっぱい

インクリメントの話

i = 0;
i = i++ + ++i;

これで i の中身はどうなるの?っていう話。
C言語(gcc)だと 3 で、JavaJavaScriptだと 2 になった。
Cはアセンブリを見るとこうなってる。

movl    $0, -12(%ebp)
leal    -12(%ebp), %eax
incl    (%eax)
movl    -12(%ebp), %edx
leal    -12(%ebp), %eax
addl    %edx, (%eax)
leal    -12(%ebp), %eax
incl    (%eax)

要するにこういうことをやってるみたい。

i = 0;
i += 1;
i = i + i;
i += 1;

代入式の前後でインクリメントされてるっぽい。なんで代入が終わってからインクリメントしてるんだよ。他のコンパイラだと結果が変わる可能性もありそうだ。
一方、JavaJavaScriptは内部で何をやってるかはわからないけど、普通に考えると

  1. i = i++ + ++i
  2. i++ + ++i を見る
  3. i++ を見る
  4. i の中身は 0 だから、2.の式は 0 + ++i になる。
  5. i をインクリメントして、i の中身は 1 になる。
  6. ++i を見る
  7. i をインクリメントして、i の中身は 2 になる。
  8. i の中身は 2 だから、2.の式は 0 + 2 になる。
  9. i = 0 + 2 で、i には 2 が代入される。

こうなるわけで、それと合ってるんだから、まあそうなってるんだろう。
Java言語仕様を読んだらそんなニュアンスだったから、たぶん合ってる。つーか前置は+や-と同じ扱いで後置は半ば特別扱いなのね。勉強になるわ。
インクリメントはややこしいから、定型文的に使うにとどめた方が良さそうだ。