これが実行されると(カーテンの後ろで)何が起こりますか?
int x = 7;
x = x++;
つまり、変数がポストインクリメントされ、1つのステートメントでそれ自体に割り当てられたときですか?これをコンパイルして実行しました。 x
はまだ7ですステートメント全体の後でもです。私の本では、x
が増加していると書かれています!
x
はインクリメントされます。ただし、x
の古い値を自分自身に割り当てています。
x = x++;
x++
はx
をインクリメントし、古い値を返します。x =
は、古い値をそれ自体に割り当てます。そのため、最終的にx
は初期値に割り当てられます。
x = x++;
と同等です
int tmp = x;
x++;
x = tmp;
ステートメント:
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インクリメント/デクリメント式の値は、オペランドの値ですbeforeインクリメント/デクリメントが行われます。 (プレフィックス形式の場合、値はオペランドの値ですafter操作、)
割り当て式のRHSが完全に評価されます(増分、減分、および/またはその他の副作用を含む)before値はLHSに割り当てられます。
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++;
ここでの微妙な点は、++
演算子が変数x
を変更することです。x + x
などの式とは異なり、 int値に評価されますが、変数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);
}
また、ほとんどの場合、大きな式で++
演算子を使用しないことをお勧めします。 whenの微妙さのため、プリインクリメントとポストインクリメントで元の変数を変更します(それぞれ++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++;
」の後に増加します。 「x = ++x;
」を実行すると8になります。
ポストインクリメント演算子は次のように機能します。
だから声明
int x = 7;
x = x++;
次のように評価されます。
したがって、xは実際に増加しますが、x ++は結果をxに代入するため、xの値は以前の値にオーバーライドされます。
インクリメントはxが呼び出された後に行われるため、xは7に等しくなります。xが呼び出されると、++ xは8になります。
x
の値を再割り当てしても、まだ7です。x = ++x
を試してください。
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
は->
が最初にxの値を1つ増やし、次にexpressionで使用することを意味します。
だからあなたの場合、x = ++x ; // where x = 7
8の値を取得します。
より明確にするために、次のコードを実行するprintfステートメントの数を調べてください。
while(i++ <5)
printf("%d" , ++i); // This might clear your concept upto great extend
++x
は事前増分->
xは増分before使用中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
非常にコンパイラに依存!