- ベストアンサー
後置インクリメントの挙動が不明で困ってます
- Eclipse 4.7 Java 8でプログラミングをやっています。
- 後置インクリメントの挙動がC言語の時と違っていて戸惑っています。
- なぜそうなるのか分からないので質問しました。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
idx = (idx < HelloWorld.length()) ? idx++ : 0; は if ( idx < HelloWorld.length() ) idx = idx++; else idx = 0; と同等かと思いますが 普通は、idx=idx++;なんて書かずに、idx++;と書くので気にすることはないですが たしかにC言語だと、環境かコンパイラによって挙動が違うようです。 idx=0; idx = idx++; printf("idx = %d\n" , idx); でテストしたら gcc4.1(32bitOS)だと、idx = 1 gcc4.8(64bitOS)だと、idx = 0 となりました。 なんとなくですが、 idx = idx++; で 右辺の計算結果の0を左辺のidxに代入したあとでidxインクリメントするのか 右辺の計算後に、idxをインクリメントしてから右辺の計算結果の0を左辺のidxへの代入をしているか の違いのような感じです。 (コンパイラの最適化のせいなのか、アーキテクチャの違いなのかわかりませんが) ともかく、 idx = idx++; のような挙動が不安定なコーディングは避けたほうがよいと思います。
その他の回答 (5)
- superside0
- ベストアンサー率64% (461/711)
> No.5 説明がわかりにくかったですかね。 C言語でも、No.3で言われているような 前置インクリメント、後置インクリメントの 仕様は、当然のことながら決定されていて、同様の挙動になります。 しかし、今回のような 同じ変数への 後置インクリメントと代入が同時に行われるようなコーディングをしてしまうと、コンパイラの最適化やアーキテクチャによっては 質問者様が、 > 後置インクリメントの挙動がC言語の時と違っていて戸惑っています。 と言われているような、idxがインクリメントしてしまうこともあれば No1でご回答されているように > その後 idxの評価された値(インクリメント前の値)が設定されるのでidxの値は変わりません。 といこともあるようなので、 「そもそもC言語の時点で、同じ変数にインクリと代入を同時に行って どちらが先に実行されるかわからないような、不安定なコーディングを していたのが問題では」という点を 強調したかったのです。
- amanojaku1
- ベストアンサー率54% (265/488)
>回答No.4 superside0 >C言語だと、環境かコンパイラによって挙動が違うようです。 Javaの場合は言語仕様として挙動は決定されています、詳細は「回答No.3 amanojaku1」参照。 それは さておき >idx = (idx < HelloWorld.length()) ? idx++ : 0; ↑これを具体的に どうすれば良いのかと言えば、下記のように修正すれば良いと思われます。 idx = (idx < HelloWorld.length()) ? idx+1 : 0;
お礼
ありがとうございます。 じつは参考書に書いてあるソースを idx = (idx < HelloWorld.length()) ? idx++ : 0; のようにしたら、この結果になったんです。 参考書には idx = (idx < HelloWorld.length()) ? idx+1 : 0; と書いてありました。 もしかしたらこのことを考慮して、こうしたの かもしれません。 これなら問題なく1加算されています。
- amanojaku1
- ベストアンサー率54% (265/488)
処理の説明は[回答No.1 wormhole]さんの方を参照して下さい。 前置と後置で処理が違うようです。 int a = 7; int b; b = a++; ↑この場合、内部的には 下記ような処理になり b = a; a = a + 1; ↑結果は「a=8」、「b=7」になります。 int a = 7; int b; b = ++a; ↑この場合、内部的には 下記ような処理になり a = a + 1; b = a; ↑結果は「a=8」、「b=8」になります。
- wormhole
- ベストアンサー率28% (1626/5665)
#1です。 ちなみにCの次のソースを試してみましたが #include <stdio.h> int main(int argc, char **argv) { int idx = 0; int length = 10; for (;;) { printf("%d\n", idx); idx = (idx < length) ? idx++ : 0; } return 0; } 延々と0が出力されます。 環境はFreeBSD-10.3で試したCコンパイラは FreeBSD clang version 3.4.1 (tags/RELEASE_34/dot1-final 208032) 20140512 gcc6 (FreeBSD Ports Collection) 6.4.0 の2つです。
お礼
なぜなんでしょう? ちなみにC言語の環境はVS2012Express DeskTopです。 環境によって動作が違うだけなんでしょうか?
- wormhole
- ベストアンサー率28% (1626/5665)
>idx = (idx < HelloWorld.length()) ? idx++ : 0;//この部分が問題の部分です 元々、問題あるコーディングかと。 idx < HelloWorld.length() が真の時には、 idxの値が評価後、idxの値がインクリメントされます。 その後 idxの評価された値(インクリメント前の値)が設定されるのでidxの値は変わりません。
お礼
つまりインクリメントしているがidxには1が代入されないという理解で いいでしょうか? 1加算されず0が代入され、その後にインクリメントされるというわけでは ないという解釈でいいのでしょうか?
お礼
インクリメントが内部でどうなっているのか理解する必要がありそうです。 >右辺の計算後に、idxをインクリメントしてから右辺の計算結果の0を左辺のi>dxへの代入をしているか そういった挙動をする可能性もあるんですね。 勉強になりました。