"x = x ++"之后的x是什么?

Mic*_*ael 273 java operators post-increment

执行此操作后会发生什么(窗帘后面)?

int x = 7;
x = x++;
Run Code Online (Sandbox Code Playgroud)

也就是说,当一个变量后期递增并在一个语句中赋值给自己时?我编译并执行了这个.在整个声明之后x仍然是7 .在我的书中,它说增加了!x

Pri*_*ley 380

x = x++;
Run Code Online (Sandbox Code Playgroud)

相当于

int tmp = x;
x++;
x = tmp;
Run Code Online (Sandbox Code Playgroud)

  • 大声笑,yay的递归定义.你可能应该完成`x = x + 1`而不是`x ++` (44认同)
  • 如果没有进一步的解释,我不认为这有用.例如,`x = ++ x;`也等于`int tmp = x; ++ X; x = tmp;`,那么通过什么逻辑我们可以推断出你的答案是正确的(它是什么)? (19认同)
  • @ user606723:不.我的意思是整个语句`x = x ++`,而不仅仅是后增量`x ++`. (8认同)
  • 更清楚它是在_asm_`x = x ++`=`MOV x,tmp; INC x; MOV tmp,x` (4认同)
  • @forker:我认为如果你使用适用于Michael正在使用的处理器的汇编指令会更清楚;) (3认同)
  • 这样更清楚:`int tmp = x; x = tmp; TMP ++;` (2认同)
  • 您还应该显示"x = ++ x"的等效项以进行比较 (2认同)

Mys*_*ial 292

x确实增加了.但是你要将旧的值分配x回自身.


x = x++;
Run Code Online (Sandbox Code Playgroud)
  1. x++递增x并返回其旧值.
  2. x = 将旧值分配给自己.

所以最后,x被分配回其初始值.

  • 然后,你会怎么说x = ++ x; (3认同)
  • 在这种情况下,@ HishamMuneer`x`在读取之前先递增,所以你最终会得到"x + 1". (3认同)

Ste*_*n C 257

该声明:

x = x++;
Run Code Online (Sandbox Code Playgroud)

相当于:

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.
Run Code Online (Sandbox Code Playgroud)

简而言之,该声明无效.

关键点:

  • Postfix递增/递减表达式的值是增量/减量发生之前的操作数的值.(在Prefix表单的情况下,该值是操作操作数的值,)

  • 将值分配给LHS 之前,完全评估赋值表达式的RHS(包括任何增量,减量和/或其他副作用).

请注意,与C和C++不同,Java中表达式的求值顺序是完全指定的,并且没有特定于平台的变化的空间.如果这不会从当前线程的角度更改执行代码的结果,则只允许编译器对操作重新排序.在这种情况下,允许编译器优化掉整个语句,因为可以证明它是无操作.


如果还不是很明显:

  • "x = x ++;" 在任何程序中几乎肯定都是错误的.
  • OP(对于原始问题!)可能意味着"x ++;" 而不是"x = x ++;".
  • 在相同变量上组合自动加/减和赋值的语句很难理解,因此无论其正确性如何都应该避免.根本不需要编写类似的代码.

希望像FindBugs和PMD这样的代码检查器会将这样的代码标记为可疑.

  • 作为旁注,OP,你可能只想说'x ++'而不是'x = x ++`. (7认同)
  • 仅仅是一个FYI:这最初发布到一个不同的问题,该问题已作为此复制品的一个副本关闭,现已合并. (4认同)
  • 正确,但可能强调增量发生*后*右手表达式评估,但*pre*赋值到左侧,因此明显的"覆盖" (3认同)
  • 这似乎是那些高中编程捻线机之一......很好地清理你的基础知识! (2认同)

use*_*092 33

int x = 7;
x = x++;
Run Code Online (Sandbox Code Playgroud)

它在C和Java中有未定义的行为,请参阅此答案.这取决于编译器会发生什么.

  • 不,它根据您引用的答案不依赖于编译器 - 请编辑 - -1现在 (4认同)
  • 对于C_,它是未定义的behavior_only.即使这样说它取决于编译器是误导 - 它意味着编译器应该指定这种行为.我还原我的投票,但考虑编辑你的答案 - 编辑:oops我不能 - 你必须先编辑它:D (2认同)

FMM*_*FMM 16

像这样的结构x = x++;表明你可能误解了++运算符的作用:

// original code
int x = 7;
x = x++;
Run Code Online (Sandbox Code Playgroud)

让我们根据删除++运算符重写这个来做同样的事情:

// 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
Run Code Online (Sandbox Code Playgroud)

现在,让我们重写它(我认为)你想要的:

// original code
int x = 7;
x++;
Run Code Online (Sandbox Code Playgroud)

这里的细微之处在于++运算符修改变量x,不像表达式那样x + x,它将计算为int值但x保持变量本身不变.考虑像古老for循环这样的构造:

for(int i = 0; i < 10; i++)
{
    System.out.println(i);
}
Run Code Online (Sandbox Code Playgroud)

请注意i++那里?它是同一个运营商.我们可以for像这样重写这个循环,它会表现得一样:

for(int i = 0; i < 10; i = i + 1)
{
    System.out.println(i);
}
Run Code Online (Sandbox Code Playgroud)

++在大多数情况下,我还建议不要在较大的表达式中使用运算符.由于微妙的时候它会修改对预后的增量(原始变量++xx++,分别),这是很容易引入微妙的错误是难以追查.


eve*_*ime 13

根据从类文件中获取的字节代码,

两个赋值都递增x,但差异是时间 when the value is pushed onto the stack

In Case1,在增量之前发生推送(然后再指定)(本质上意味着你的增量什么都不做)

Case2,增量首先发生(使其成为8),然后推入堆栈(然后分配给x)

情况1:

int x=7;
x=x++;
Run Code Online (Sandbox Code Playgroud)

字节代码:

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
Run Code Online (Sandbox Code Playgroud)

案例2:

int x=7; 
x=++x;
Run Code Online (Sandbox Code Playgroud)

字节代码

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
Run Code Online (Sandbox Code Playgroud)
  • 这里的堆栈是指操作数堆栈,本地:x索引:1类型:int


F.J*_*F.J 9

它在" x = x++;" 之后递增.如果你做" x = ++x;" 那就是8 .

  • 如果它在`x = x ++`之后递增,那么它应该是8. (4认同)

小智 7

在调用x之后发生递增,因此x仍然等于7.当调用x时,++ x将等于8


Vis*_*hal 7

重新分配值时,x它仍然是7.尝试x = ++x,你会得到其他8

x++; // don't re-assign, just increment
System.out.println(x); // prints 8
Run Code Online (Sandbox Code Playgroud)


Gau*_*hra 7

Post Increment运算符的工作方式如下:

  1. 存储操作数的上一个值.
  2. 增加操作数的值.
  3. 返回操作数的先前值.

所以声明

int x = 7;
x = x++; 
Run Code Online (Sandbox Code Playgroud)

评估如下:

  1. x用值7初始化
  2. post increment operator存储x的先前值,即返回7.
  3. 增加x,所以现在x是8
  4. 返回x的前一个值,即7,并将其分配回x,因此x再次变为7

所以x确实增加了,但是因为x ++将结果赋给x,所以x的值被覆盖到它之前的值.


jos*_*hus 6

因为x ++会在将值赋给变量后递增值.所以在执行这一行时:

x++;
Run Code Online (Sandbox Code Playgroud)

变量x仍将具有原始值(7),但在另一行上再次使用x,例如

System.out.println(x + "");
Run Code Online (Sandbox Code Playgroud)

会给你8.

如果要在赋值语句中使用递增的x值,请使用

++x;
Run Code Online (Sandbox Code Playgroud)

这会将x递增1,然后将该值赋给变量x.

[编辑]而不是x = x ++,它只是x ++; 前者将x的原始值分配给它自己,所以它实际上在该行上没有任何作用.