执行此操作后会发生什么(窗帘后面)?
int x = 7;
x = x++;
也就是说,当一个变量后期递增并在一个语句中赋值给自己时?我编译并执行了这个。在整个声明之后,x
仍然是7。在我的书中,它说x
增加了!
x
确实增加了。但是你将x
的旧值重新分配给自己。
x = x++;
x++
增加x
并返回其旧值。x =
将旧的价值归还给自己。所以最后,x
被分配回其初始值。
Post Increment运算符的工作方式如下:
所以声明
int x = 7;
x = x++;
评估如下:
所以x确实增加了,但是因为x ++将结果赋给x,所以x的值被覆盖到它之前的值。
因为x ++会在将值赋给变量后递增值。所以在执行这一行时:
x++;
变量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,然后在表达式中使用。
所以在你的情况下,如果你做x = ++x ; // where x = 7
你会得到8的价值。
为了更清楚,请尝试找出有多少printf语句将执行以下代码
while(i++ <5)
printf("%d" , ++i); // This might clear your concept upto great extend
++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
非常依赖编译器!
我认为这个争议可以在不进入代码和思考的情况下得到解决。
考虑将i ++和++ i作为函数,比如Func1和Func2。
现在i = 7; Func1(i ++)返回7,Func2(++ i)返回8(每个人都知道这一点)。在内部,两个函数都将i递增到8,但它们返回不同的值。
所以i = i ++调用函数Func1。在函数内部,我增加到8,但在完成时函数返回7。
所以最终7分配给我。 (所以最后,i = 7)
x = x ++;
这是后增量运算符。应该理解为“使用操作数的值然后递增操作数”。
如果要反转,即“递增操作数然后使用操作数的值”,则必须使用预增量运算符,如下所示。
x = ++ x;
此运算符首先将x的值递增1,然后将该值赋值回x。
这是因为您使用了后增量运算符。在以下代码行中
x = x++;
会发生什么,你将x的值赋给x。 x的值分配给x后,x ++递增x。这就是后增量运算符的工作方式。它们在声明执行后工作。所以在你的代码中,x先返回,然后再增加。
如果你这样做了
x = ++x;
答案是8,因为你使用了预增量运算符。这会在返回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.
简而言之,该声明无效。
关键点:
请注意,与C和C ++不同,Java中表达式的求值顺序是完全指定的,并且没有特定于平台的变化的空间。如果这不会从当前线程的角度更改执行代码的结果,则只允许编译器对操作重新排序。在这种情况下,允许编译器优化掉整个语句,因为可以证明它是无操作。
如果还不是很明显:
希望像FindBugs和PMD这样的代码检查器会将这样的代码标记为可疑。
int x = 7;
x = x++;
It has undefined behaviour in C和Java见this answer。这取决于编译器会发生什么。
像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++
)中修改原始变量的微妙性,因此很容易引入难以追踪的细微错误。
According to Byte code从类文件中获取,
两个赋值都增加x,但差异是when the value is pushed onto the stack
的时间
在Case1
中,Push在增量之前发生(然后被赋值)(本质上意味着你的增量什么都不做)
在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 = x++;
”之后递增。如果你做“x = ++x;
”,它将是8。
在调用x之后发生递增,因此x仍然等于7.当调用x时,++ x将等于8
当您重新分配x
的值时,它仍然是7.尝试x = ++x
,你会得到其他8
x++; // don't re-assign, just increment
System.out.println(x); // prints 8