これが実行されると、(カーテンの後ろで) 何が起こりますか?
int x = 7;
x = x++;
つまり、変数がポストインクリメントされ、1 つのステートメントでそれ自体に割り当てられる場合はどうなるでしょうか? これをコンパイルして実行しました。ステートメント全体の後でx
も 7 のままです。私の本では、それはインクリメントされていると言っています!x
これが実行されると、(カーテンの後ろで) 何が起こりますか?
int x = 7;
x = x++;
つまり、変数がポストインクリメントされ、1 つのステートメントでそれ自体に割り当てられる場合はどうなるでしょうか? これをコンパイルして実行しました。ステートメント全体の後でx
も 7 のままです。私の本では、それはインクリメントされていると言っています!x
x = x++;
と同等です
int tmp = x;
x++;
x = tmp;
x
インクリメントされます。しかし、古い値をx
それ自体に割り当てています。
x = x++;
x++
インクリメントx
して古い値を返します。x =
古い値を自分自身に割り当てます。したがって、最終的にx
は初期値に戻されます。
ステートメント:
x = x++;
と同等です:
tmp = x; // ... this is capturing the value of "x++"
x = x + 1; // ... this is the effect of the increment operation in "x++" which
// happens after the value is captured.
x = tmp; // ... this is the effect of assignment operation which is
// (unfortunately) clobbering the incremented value.
つまり、このステートメントは効果がありません。
キーポイント:
Postfixインクリメント/デクリメント式の値は、インクリメント/デクリメントが行われる前のオペランドの値です。(プレフィックス形式の場合、値は演算後のオペランドの値です)
値がLHSに割り当てられる前に、代入式のRHSが完全に評価されます(増分、減分、および/またはその他の副作用を含む) 。
CやC++とは異なり、Javaでの式の評価の順序は完全に指定されており、プラットフォーム固有のバリエーションの余地はありません。コンパイラーは、現在のスレッドの観点からコードを実行した結果を変更しない場合にのみ、操作を並べ替えることができます。この場合、コンパイラーはステートメント全体を最適化することが許可されます。これは、それがノーオペレーションであることが証明できるためです。
まだ明らかでない場合:
うまくいけば、FindBugsやPMDのようなコードチェッカーは、このようなコードを疑わしいものとしてフラグを立てます。
int x = 7;
x = x++;
C では未定義の動作があり、Java についてはこの回答を参照してください。何が起こるかはコンパイラに依存します。
次のような構文x = x++;
は、おそらく++
演算子の機能を誤解していることを示しています。
// original code
int x = 7;
x = x++;
++
演算子を削除することに基づいて、同じことを行うようにこれを書き直しましょう。
// behaves the same as the original code
int x = 7;
int tmp = x; // value of tmp here is 7
x = x + 1; // x temporarily equals 8 (this is the evaluation of ++)
x = tmp; // oops! we overwrote y with 7
さて、あなたが望んでいたこと(私が思うに)をするためにそれを書き直しましょう:
// original code
int x = 7;
x++;
ここでの微妙な点は、int 値に評価されるが変数自体は変更されないままになるなどの式とは異なり、++
演算子が変数 を変更することです。x
由緒あるループのような構造を考えてみましょう:x + x
x
for
for(int i = 0; i < 10; i++)
{
System.out.println(i);
}
そこに注目i++
?同じオペレーターです。このfor
ループを次のように書き直すと、同じように動作します。
for(int i = 0; i < 10; i = i + 1)
{
System.out.println(i);
}
++
また、ほとんどの場合、より大きな式で演算子を使用しないことをお勧めします。プリインクリメントとポストインクリメント (それぞれと) で元の変数を変更するタイミングが微妙であるため、追跡が困難な微妙なバグが非常に簡単に導入されます。++x
x++
クラスファイルから取得したバイトコードによると、
どちらの割り当ても x をインクリメントしますが、違いは次のタイミングです。when the value is pushed onto the stack
ではCase1
、インクリメントの前にプッシュが発生します (その後、割り当てられます) (基本的に、インクリメントは何もしないことを意味します)。
ではCase2
、インクリメントが最初に発生し (8 になる)、次にスタックにプッシュされます (次に x に割り当てられます)。
ケース 1:
int x=7;
x=x++;
バイトコード:
0 bipush 7 //Push 7 onto stack
2 istore_1 [x] //Pop 7 and store in x
3 iload_1 [x] //Push 7 onto stack
4 iinc 1 1 [x] //Increment x by 1 (x=8)
7 istore_1 [x] //Pop 7 and store in x
8 return //x now has 7
ケース 2:
int x=7;
x=++x;
バイトコード
0 bipush 7 //Push 7 onto stack
2 istore_1 [x] //Pop 7 and store in x
3 iinc 1 1 [x] //Increment x by 1 (x=8)
6 iload_1 [x] //Push x onto stack
7 istore_1 [x] //Pop 8 and store in x
8 return //x now has 8
" " の後にインクリメントされますx = x++;
。「 」をすると8になりますx = ++x;
。
x が呼び出された後にインクリメントが発生するため、x は引き続き 7 に等しくなります。x が呼び出されると、++x は 8 に等しくなります。
値を再割り当てしてx
も7のままです。試してみるx = ++x
と、8が得られます。
x++; // don't re-assign, just increment
System.out.println(x); // prints 8
x++ は、変数に割り当てた後に値をインクリメントするためです。以下の行の実行中も同様です。
x++;
varialbe x は元の値 (7) のままですが、次のように別の行で x を再度使用します。
System.out.println(x + "");
あなたに8を与えます。
割り当てステートメントで x の増分値を使用する場合は、次を使用します。
++x;
これにより、x が 1 ずつインクリメントされ、その値が変数 x に割り当てられます。
[編集] x = x++ ではなく、単に x++ です。前者は x の元の値をそれ自体に割り当てるため、実際にはその行では何もしません。
次の場合はどうなりint x = 7; x = x++;
ますか?
ans -> x++
は、最初に式に x の値を使用し、次にそれを 1 増やすことを意味します。
これがあなたの場合に起こります。RHS の x の値が LHS の変数 x にコピーされ、値がx
1 増加します。
同様に、最初に x の値を 1 増やしてから、式で使用することを++x
意味 します。
したがって、あなたの場合、そうすると
、8の値が得られます。 ->
x = ++x ; // where x = 7
より明確にするために、次のコードを実行する printf ステートメントの数を調べてみてください
while(i++ <5)
printf("%d" , ++i); // This might clear your concept upto great extend
++x
プレインクリメント ->
x は使用前
x++
にインクリメントされます ポストインクリメント->
x は使用後にインクリメントされます
int x = 7; -> x get 7 value <br>
x = x++; -> x get x value AND only then x is incremented
つまり、これは次
x++
のことを意味します。x = x+1
なぜなら:
int x = 7; x = x++;
x is 7
int x = 7; x = x = x+1;
x is 8
そして今、それは少し奇妙に思えます:
int x = 7; x = x+=1;
x is 8
コンパイラに大きく依存します!
x = x++;
これはポストインクリメント演算子です。「オペランドの値を使用してから、オペランドをインクリメントする」と理解する必要があります。
逆に、つまり「オペランドをインクリメントしてからオペランドの値を使用する」ようにしたい場合は、以下に示すようにプリインクリメント演算子を使用する必要があります。
x = ++x;
この演算子は、最初に x の値を 1 増やしてから、その値を x に割り当てます。