What's the difference between X = X++; vs X++;?
你以前试过这个吗?
1 2 3 4 5 6 | static void Main(string[] args) { int x = 10; x = x++; Console.WriteLine(x); } |
产量:10。
但为了
1 2 3 4 5 6 | static void Main(string[] args) { int x = 10; x++; Console.WriteLine(x); } |
产量:11。
有人能解释一下为什么吗?
X+++将增值,但返回旧价值。
So in this case:
1 2 3 4 5 6 | static void Main(string[] args) { int x = 10; x = x++; Console.WriteLine(x); } |
你有X在11秒之内,然后返回到10,因为10是返回值。
你可以为了同样的结果而这样做:
ZZU1
还值得一提的是,如果你做了以下事情,你会有11个预期结果:
1 2 3 4 5 6 | static void Main(string[] args) { int x = 10; x = ++x; Console.WriteLine(x); } |
在分配中,你首先提取
也许,一个等效的代码可以清晰地说明:
1 2 3 | var tmp = x; x++; x = tmp; |
这是您在C x1 x0中的等价代码。
X++的行为是增量X,但在增量之前回报价值。它称之为这一原因的增量。
so x=x++;simply put will
1回报价值
二增量X
三指定原始值(返回步骤1)从x到x。
1 2 | x = 10 x = ++x |
终结等于11。
1 | x++; |
Does the following:
1 2 3 | int returnValue = x; x = x+1; return returnValue; |
如你所见,原始值是保存的,X是增量的,然后原始值是返回的。
这个结尾所做的是在某个地方保留10个价值,设置X等于11个,然后再返回10个原因X等于10个。注意到X实际成为一个小环的11(假设没有编译器优化)。
这不是直接回答问题,但为什么世界上没有人会使用
1 | x = x++; |
?
这完全违背了后增量/前增量算子的目的。
你可以这样想:
1 | int x = 10; |
X是一个集装箱,而集装箱是一个价值,10。
1 | x = x++; |
This can be broken down to:
1 2 3 4 5 6 7 8 | 1) increment the value contained in x now x contains 11 2) return the value that was contained in x before it was incremented that is 10 3) assign that value to x now, x contains 10 |
现在,打印包含在X中的值
1 | Console.WriteLine(x); |
而且,毫不惊讶地,它打印出10。
通过定义,X++,返回X值,然后增量X。
http://blogs.msdn.com/lucabol/archive/2004/08/31/223580.aspx
你做的第一件事叫做"后增量",意思是
1 2 3 | int x = 10; x++; //x still is 10 Console.WriteLine(x); //x is now 11(post increment) |
所以,当你指定x=x++;x仍然是你能做的10,如果你需要x在这一行是11,那么写+x(如果我错了,认为它叫做预增量纠正我)。或者,右X++;和大于X=X++;
问题是,它取决于行还是语句,表示它将在之后递增;?
也许我不对,但我更容易理解类似例子的结果:
1 2 3 4 5 6 7 | public static void main(String[] args) { int x = 10; int y = 0; y = x + x++; //1, 2, 3, 4 x += x; //5 System.out.println("x =" + x +"; y =" + y); //6 } |
让我们一步一步地看看操作y=x+x+:
现在,让我们回到我们的示例并执行相同的步骤:
1 2 3 4 5 | public static void main(String[] args) { int x = 10; x = x++; //1, 2, 3, 4 System.out.println(x); //5 } |
将增量运算符放在变量后意味着增量和赋值发生在表达式被计算之后…所以原始报表x=x++;翻译为1。计算x并将值存储在暴君内存中…现在执行由++运算符调用的代码….(步骤2和3)2。x的增量值(在瞬态存储器中)三。将增量值分配给X的存储位置…现在,继续执行行的其余部分,在左边有一个=符号…5。因此,将步骤1中存储的值(未创建的值)赋给=符号左侧的表达式…哪个是X
试着呼唤++X并看看是否该工作。
我知道有很多答案,一个被接受的答案,但我还是会把我的两分钱投入另一个观点。
我知道这个问题是C,但是我假设对于像后缀操作符这样的东西,它与C没有不同的行为:
1 2 3 4 5 | int main(){ int x = 0; while (x<1) x = x++; } |
编译器生成的程序集(是的,我对其进行了编辑以使其更具可读性)显示
1 2 3 4 5 6 7 8 9 10 11 12 13 | ... mov -8(rbp), 0 ; x = 0 L1: cmp -8(rbp), 1 ; if x >= 1, jge L2 ; leave the loop mov eax, -8(rbp) ; t1 = x mov ecx, eax ; t2 = t1 add ecx, 1 ; t2 = t2 + 1 mov -8(rbp), ecx ; x = t2 (so x = x + 1 !) mov -8(rbp), eax ; x = t1 (kidding, it's the original value again) jmp L1 L2: ... |
同样地,循环的作用是:
1 2 3 | t = x x = x + 1 x = t |
注意:打开任何优化都会得到如下一些装配结果:
1 2 3 4 | ... L1: jmp L1 ... |
存储你告诉它给x的值甚至不麻烦!
作为一个标准声明,
1 2 | int x = 10; int y = (x++) + 2; |
我们将获得EDOCX1和EDOCX1。X的电流值被分配,然后X的增量和转换被定位。so,when using the same variable,
1 2 3 4 | int x = 10; // Create a variable x, and assign an initial value of 10. x = x++; // First, assign the current value of x to x. (x = x) // Second, increment x by one. (x++ - first part) // Third, assign the new value of x to x. (x++ - second part) |
不管你怎么看,X的新值是11。
我完全错了。
简单说明:
X++是一个后缀递增。
编译器的作用:
a)将x的值赋给xb)增加临时值x(我想它可能会被优化掉)c)丢弃临时值x
如果您希望代码随作业返回11,请编写:
x=++x;
The result of the assignment
1 | x = x++; |
是在C++++++++++++++++++++++++++++++++++++++++++
因此,操作的实际顺序取决于编译员如何决定执行,而在分配或增量将首先出现的地方,则没有任何保障。(This is well defined in C 35;as Jon Skeet pointed out in the comments.虽然我现在感觉到这个答案是无价的,但我一直在写这封信,以回答作者的问题和评论。)
然而,在本案中,这一事件发生的次序如下:
在这种情况下,尽管增量出现了,但它被分配给旧价值的X过滤。
HTH