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

IT小君   2021-12-09T02:31:41

执行此操作时(幕后)会发生什么?

int x = 7;
x = x++;

也就是说,当一个变量在一个语句中被后递增并分配给它自己时?我编译并执行了这个。即使在整个语句之后x仍然是 7 在我的书中,它说这是递增的!x

评论(18)
IT小君
x = x++;

相当于

int tmp = x;
x++;
x = tmp;
2021-12-09T02:31:42   回复
IT小君

x确实会增加。但是您正在将xback的旧值分配给自身。


x = x++;
  1. x++递增x并返回其旧值。
  2. x = 将旧值分配回自身。

所以最后,x被分配回它的初始值。

2021-12-09T02:31:42   回复
IT小君

该声明:

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.

简而言之,该语句无效。

关键点:

  • 后缀递增/递减表达式的值是递增/递减发生之前操作数的值(在Prefix形式的情况下,该值是操作的操作数的值,)

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

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


如果还不是很明显:

  • "x = x++;" 在任何程序中几乎肯定是一个错误。
  • OP(对于原始问题!)可能意味着“x++;” 而不是“x = x++;”。
  • 将 auto inc/decrement 和赋值结合到同一个变量上的语句很难理解,因此无论它们的正确性如何都应该避免根本不需要编写那样的代码。

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

2021-12-09T02:31:42   回复
IT小君
int x = 7;
x = x++;

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

2021-12-09T02:31:42   回复
IT小君

类似的构造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);
}

我还建议不要++在大多数情况下在较大的表达式中使用运算符。由于它在前后增量(分别为)中修改原始变量的微妙之处,因此很容易引入难以追踪的细微错误。++xx++

2021-12-09T02:31:43   回复
IT小君

根据从类文件中得到的字节码

两个赋值都增加了 x,但不同的是 when the value is pushed onto the stack

Case1, Push 在增量之前发生(然后分配)(本质上意味着您的增量什么都不做)

In Case2, Increment 首先发生(使其为 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
2021-12-09T02:31:43   回复
IT小君

Post Increment 运算符的工作原理如下:

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

所以声明

int x = 7;
x = x++; 

将被评估如下:

  1. x 初始化为值 7
  2. 后增量运算符存储 x 的先前值,即 7 以返回。
  3. 增加 x,所以现在 x 是 8
  4. 返回 x 的先前值,即 7 并将其分配回 x,因此 x 再次变为 7

所以 x 确实增加了,但由于 x++ 将结果分配回 x 所以 x 的值被覆盖为其先前的值。

2021-12-09T02:31:43   回复
IT小君

它在“ x = x++;之后递增如果您执行“ x = ++x;”,则为 8

2021-12-09T02:31:44   回复
IT小君

递增发生在 x 被调用之后,所以 x 仍然等于 7。当 x 被调用时,++x 将等于 8

2021-12-09T02:31:44   回复
IT小君

当你重新分配x的值仍然是 7. 尝试x = ++x,你会得到 8 否则做

x++; // don't re-assign, just increment
System.out.println(x); // prints 8
2021-12-09T02:31:44   回复
IT小君

因为 x++ 会在将值分配给变量后递增该值。依此类推,并在此行执行期间:

x++;

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

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

会给你8。

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

++x;

这将使 x 增加 1,然后将该值分配给变量 x。

[编辑] 而不是 x = x++,它只是 x++;前者将 x 的原始值分配给自身,因此它实际上在该行上什么都不做。

2021-12-09T02:31:44   回复
IT小君

什么时候发生int x = 7; x = x++;

ans -> x++表示首先使用 x 的值进行表达式,然后将其增加 1。
这就是您的情况。将 RHS 上 x 的值复制到 LHS 上的变量 x 中,然后将 的值x增加 1。

类似的++x 意思 ->是先将 x 的值加一,然后在表达式中使用。
因此,在您的情况下,如果您这样做, x = ++x ; // where x = 7
您将获得 8 的价值。

为了更清楚,尝试找出多少 printf 语句将执行以下代码

while(i++ <5)   
  printf("%d" , ++i);   // This might clear your concept upto  great extend
2021-12-09T02:31:44   回复
IT小君

++x被预增量 ->x递增之前被使用
x++是后递增->x递增正在使用

int x = 7; -> x get 7 value <br>
x = x++; -> x get x value AND only then x is incremented
2021-12-09T02:31:45   回复
IT小君

所以这意味着: 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

非常依赖编译器!

2021-12-09T02:31:45   回复
IT小君

最简单的解释!

这是因为 ++ 在操作数之后进行后递增,这意味着首先将值分配给变量然后递增。如果您期望 x 值为 8,那么您应该像下面提到的那样预先增加它: 在此处输入图片说明

2021-12-09T02:31:45   回复
IT小君

x = x++;

这是后增量运算符。应该理解为“使用操作数的值,然后递增操作数”。

如果您希望发生相反的情况,即“递增操作数,然后使用操作数的值”,则必须使用预递增运算符,如下所示。

x = + + x;

此运算符首先将 x 的值增加 1,然后将该值分配回 x。

2021-12-09T02:31:46   回复
IT小君

我认为无需编写代码和思考即可解决此争议。

将 i++ 和 ++i 视为函数,比如 Func1 和 Func2。

现在 i=7;
Func1(i++) 返回 7,Func2(++i) 返回 8(这个大家都知道)。在内部,这两个函数都将 i 增加到 8 ,但它们返回不同的值。

所以 i = i++ 调用函数 Func1。在函数内部 i 递增到 8,但完成后函数返回 7。

所以最终 7 被分配给 i。(所以最后,i = 7)

2021-12-09T02:31:46   回复
IT小君

这是因为您使用了后增量运算符。在下面这行代码中

x = x++;

发生的情况是,您将 x 的值分配给 x。x++ 在将 x 的值分配给 x 后增加 x。这就是后增量运算符的工作方式。它们在执行语句后工作。因此,在您的代码中, x 首先返回,然后再递增。

如果你做了

x = ++x;

答案是 8,因为您使用了预增量运算符。这会在返回 x 的值之前先增加值。

2021-12-09T02:31:46   回复