304

これが実行されると、(カーテンの後ろで) 何が起こりますか?

int x = 7;
x = x++;

つまり、変数がポストインクリメントされ、1 つのステートメントでそれ自体に割り当てられる場合はどうなるでしょうか? これをコンパイルして実行しました。ステートメント全体の後でxも 7 のままです。私の本では、それはインクリメントされていると言っています!x

4

18 に答える 18

396
x = x++;

と同等です

int tmp = x;
x++;
x = tmp;
于 2011-10-27T04:42:19.700 に答える
325

xインクリメントされます。しかし、古い値をxそれ自体に割り当てています。


x = x++;
  1. x++インクリメントxして古い値を返します。
  2. x =古い値を自分自身に割り当てます。

したがって、最終的にxは初期値に戻されます。

于 2011-10-27T04:41:44.050 に答える
262

ステートメント:

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での式の評価の順序は完全に指定されており、プラットフォーム固有のバリエーションの余地はありません。コンパイラーは、現在のスレッドの観点からコードを実行した結果を変更しない場合にのみ、操作を並べ替えることができます。この場合、コンパイラーはステートメント全体を最適化することが許可されます。これは、それがノーオペレーションであることが証明できるためです。


まだ明らかでない場合:

  • "x = x ++;" ほぼ間違いなく、どのプログラムでも間違いです。
  • OP(元の質問の場合!)はおそらく「x++;」を意味していました。「x=x++;」ではなく。
  • 同じ変数で自動インクリメント/デクリメントと割り当てを組み合わせたステートメントは理解しにくいため正確性に関係なく避ける必要があります。そのようなコードを書く必要はありません。

うまくいけば、FindBugsやPMDのようなコードチェッカーは、このようなコードを疑わしいものとしてフラグを立てます。

于 2012-08-20T07:26:04.653 に答える
33
int x = 7;
x = x++;

C では未定義の動作があり、Java についてはこの回答を参照してください。何が起こるかはコンパイラに依存します。

于 2011-10-27T12:51:04.040 に答える
16

次のような構文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 + xxfor

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);
}

++また、ほとんどの場合、より大きな式で演算子を使用しないことをお勧めします。プリインクリメントとポストインクリメント (それぞれと) で元の変数を変更するタイミングが微妙であるため、追跡が困難な微妙なバグが非常に簡単に導入されます。++xx++

于 2012-08-20T15:02:29.957 に答える
14

クラスファイルから取得したバイトコードによると、

どちらの割り当ても 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 インデックス: 1 タイプ: int
于 2014-08-28T15:22:40.167 に答える
8

" " の後にインクリメントされますx = x++;。「 」をすると8になりますx = ++x;

于 2011-10-27T04:41:39.010 に答える
7

x が呼び出された後にインクリメントが発生するため、x は引き続き 7 に等しくなります。x が呼び出されると、++x は 8 に等しくなります。

于 2011-10-27T04:43:14.360 に答える
7

値を再割り当てしてxも7のままです。試してみるx = ++xと、8が得られます。

x++; // don't re-assign, just increment
System.out.println(x); // prints 8
于 2011-10-27T04:43:16.870 に答える
6

x++ は、変数に割り当てた後に値をインクリメントするためです。以下の行の実行中も同様です。

x++;

varialbe x は元の値 (7) のままですが、次のように別の行で x を再度使用します。

System.out.println(x + "");

あなたに8を与えます。

割り当てステートメントで x の増分値を使用する場合は、次を使用します。

++x;

これにより、x が 1 ずつインクリメントされ、その値が変数 x に割り当てられます。

[編集] x = x++ ではなく、単に x++ です。前者は x の元の値をそれ自体に割り当てるため、実際にはその行では何もしません。

于 2011-10-27T14:22:47.880 に答える
4

次の場合はどうなりint x = 7; x = x++;ますか?

ans -> x++は、最初に式に x の値を使用し、次にそれを 1 増やすことを意味します。
これがあなたの場合に起こります。RHS の x の値が LHS の変数 x にコピーされ、値がx1 増加します。

同様に、最初に x の値を 1 増やしてから、式で使用することを++x 意味 します。 したがって、あなたの場合、そうすると 、8の値が得られます。 ->
x = ++x ; // where x = 7

より明確にするために、次のコードを実行する printf ステートメントの数を調べてみてください

while(i++ <5)   
  printf("%d" , ++i);   // This might clear your concept upto  great extend
于 2011-10-27T08:41:15.690 に答える
3

++xプレインクリメント ->x は使用
x++にインクリメントされます ポストインクリメント->x は使用後にインクリメントされます

int x = 7; -> x get 7 value <br>
x = x++; -> x get x value AND only then x is incremented
于 2011-10-27T15:58:03.867 に答える
1

つまり、これは次 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

コンパイラに大きく依存します!

于 2011-10-27T13:15:28.237 に答える
-1

x = x++;

これはポストインクリメント演算子です。「オペランドの値を使用してから、オペランドをインクリメントする」と理解する必要があります。

逆に、つまり「オペランドをインクリメントしてからオペランドの値を使用する」ようにしたい場合は、以下に示すようにプリインクリメント演算子を使用する必要があります。

x = ++x;

この演算子は、最初に x の値を 1 増やしてから、その値を x に割り当てます。

于 2014-12-14T05:50:34.183 に答える