これが実行されると(カーテンの後ろで)何が起こりますか?
int x = 7;
x = x++;
つまり、変数がポストインクリメントされ、1つのステートメントでそれ自体に割り当てられると、これをコンパイルして実行しました。ステートメント全体の後でさえ、x
まだ7 です。私の本では、それはインクリメントされていると言っています!x
x += 1
多分ループ内を除いて、私はを使用したいと思います。for(int x=0; x<7; x++)
これが実行されると(カーテンの後ろで)何が起こりますか?
int x = 7;
x = x++;
つまり、変数がポストインクリメントされ、1つのステートメントでそれ自体に割り当てられると、これをコンパイルして実行しました。ステートメント全体の後でさえ、x
まだ7 です。私の本では、それはインクリメントされていると言っています!x
x += 1
多分ループ内を除いて、私はを使用したいと思います。for(int x=0; x<7; x++)
回答:
x
増加します。しかし、あなたx
自身の中に古い価値を割り当てています。
x = x++;
x++
x
古い値をインクリメントして返します。x =
古い値をそれ自体に割り当てます。つまり、最終的にx
は、初期値に割り当てられます。
x = x++;
に相当
int tmp = x;
x++;
x = tmp;
x=x+1
代わりに行うべきでしたx++
x = x++
投稿の増分だけでなく、ステートメント全体を意味しましたx++
。
x = ++x;
同じであるというのは真実ではないint tmp = x; ++x; x = tmp;
ので、どのロジックであなたの答えが正しいと推測できますか?
x=x++
=MOV x,tmp; INC x; MOV tmp,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などのコードチェッカーが、このようなコードに疑わしいフラグを立てます。
x++
代わりに単に言うことを意味しますx = x++
。
のような構成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);
}
また++
、ほとんどの場合、より大きな式で演算子を使用しないことをお勧めします。ための繊細さの場合、それは前対後インクリメント(元の変数を変更++x
し、x++
それぞれ)、それは非常に簡単に追跡することが困難である微妙なバグを導入することです。
クラスファイルから取得したバイトコードによると、
両方の割り当てはxをインクリメントしますが、違いはタイミングです when the value is pushed onto the stack
ではCase1
、Pushはインクリメントの前に発生し(その後、割り当てられます)(基本的に、インクリメントが何もしないことを意味します)
では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になります。
x = x++
、それは8であるべきである
増分後演算子は次のように機能します。
したがって、ステートメント
int x = 7;
x = x++;
次のように評価されます。
したがって、xは確かに増加しますが、x ++は結果をxに割り当てているため、xの値は以前の値に上書きされます。
これは、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
することを意味 ->
します。
したがって、あなたのケースでは、あなた x = ++x ; // where x = 7
が8の値を得るでしょう。
より明確にするために、次のコードを実行するprintfステートメントの数を調べてください。
while(i++ <5)
printf("%d" , ++i); // This might clear your concept upto great extend
x
8になりますが、7です-読み取りと割り当ての間でインクリメントが発生します
++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 + 1, x-1)
Cのようになり、コンマで区切られた式が許可されます。
この論争は、コードに踏み込むことなく、ただ考えるだけで解決できると思います。
関数としてi ++と++ iを考えてください。
今i = 7;
Func1(i ++)は7を返し、Func2(++ i)は8を返します(誰もが知っています)。内部的にはどちらの関数もiを8にインクリメントしますが、返す値は異なります。
したがって、i = i ++は関数Func1を呼び出します。関数内ではiが8にインクリメントされますが、完了すると関数は7を返します。
したがって、最終的に7がiに割り当てられます。(結局、i = 7)
int x = 7; x = ++x;
もちろん、それでも恐ろしいコードです。再割り当てする必要はありません。int x = 7; x++;
十分です