- PR -

代入とインクリメント演算子

1
投稿者投稿内容
なかさん
会議室デビュー日: 2005/02/22
投稿数: 3
投稿日時: 2005-04-28 00:32
インクリメント演算子について、質問があります。
以下のコードを実行すると、結果としてxの値は0と出力されますが
これはなぜなのでしょうか?

処理の流れとして
@xにインクリメントする前の値(すなわち0のまま)がセットされる。
Axがインクリメントされる。(1に更新される)
となって1が出力されるような気がするのですが。

int x = 0;
x = x++;
System.out.println("x = " + x);

逆に
int x = 0;
x = ++x;
System.out.println("x = " + x);

とした場合、
@xがインクリメントされる。(1に更新される)
Axにインクリメントした値(すなわち1)がセットされる。
という流れになると考えられ、実際の結果も1が出力されます。

どなたかご存知の方がおられましたら、ご教授いただきたいと思います。
よろしくお願いいたします。
Kissinger
ぬし
会議室デビュー日: 2002/04/30
投稿数: 428
お住まい・勤務地: 愛知県
投稿日時: 2005-04-28 01:14
なかさん、こんにちは。

引用:
@xにインクリメントする前の値(すなわち0のまま)がセットされる。


の理解が誤っているのだと思います。
前置か後置かの違いは、その部分の値が決まる順序を規定しているのであって、
代入の順序にまで影響を与えません。

言語仕様では、代入演算子の優先順は最低です。
x = x++;では、代入は最後に行われます。
x++ の評価結果は ++を実行する前の値であるゼロになります。
評価結果のゼロが決まった後に ++が実行されます。
最後に、評価結果のゼロを xに代入しますから、xはゼロになります。

これが正しく理解できたとしても、プログラムの読みやすさを考えれば
1つの式で、変数を2回以上変更するのは避けたほうが無難です。
なかさん
会議室デビュー日: 2005/02/22
投稿数: 3
投稿日時: 2005-04-28 01:38
回答ありがとうございます。

x = x++; の処理の流れとして

@左辺の式の評価 (x (=0)のまま)
A右辺の式の評価 (インクリメントする前のx(=0))
Bxのインクリメントを行う(xが1に更新)
C @、Aの評価の結果に従って、代入(Aの評価が0であるためxが1から0に更新)

ということになるということでしょうか。

x = ++x;の場合だと
@左辺の式の評価 (x (=0)のまま)
Axのインクリメントを行う(xが1に更新)
B右辺の式の評価 (インクリメントした後のx(=1))
C @、Bの評価の結果に従って、代入(Bの評価が1であるためxが0から1に更新)

になるのですね。

代入が変数に格納された値で行われるというより、
式の評価の結果で行われるということで理解しました。

どちらにしても、読みにくいコードですので、使用は避けることとします。
coasm
大ベテラン
会議室デビュー日: 2001/11/26
投稿数: 237
投稿日時: 2005-04-28 03:47
クラスファイルを逆アセンブルしてみれば一目瞭然なのですが、
x = x++; という式は、
iload_1
iinc 1, 1
istore_1
のようにコンパイルされます。

つまり、
(1) xの値を取り出す。
(2) xをインクリメントする。
(3) (1)で取り出した値をxに代入する。
という動作です。
aa
ぬし
会議室デビュー日: 2004/01/08
投稿数: 299
投稿日時: 2005-04-28 06:54
x++ や ++x は、単純に言えば x = x + 1 をしているわけですから、例えば

for (int i = 0; i < 3000; i++)

とか、

a = array[i++];

とかいう使い方をします。

for (int i = 0; i < 3000; i++)
for (int i = 0; i < 3000; ++i)

ならやっていることは一緒ですけど、

a = array[i++];
a = array[++i];

ならやっていることは違います。

y = x++;
y = ++x;

なら分かりますが、

x = x++;
x = ++x;

というのは無意味です。

x = x + 1 という意味で使いたいなら単純に

x++;
++x;

と書けばいいです。同じ変数に代入するから話がおかしくなります。
1

スキルアップ/キャリアアップ(JOB@IT)