X = X ++有什么区别 vs X ++;?
你曾经尝试过吗?
static void Main(string[] args) { int x = 10; x = x++; Console.WriteLine(x); }
输出:10。
但对于
static void Main(string[] args) { int x = 10; x++; Console.WriteLine(x); }
输出:11。
谁能解释为什么这个?
X ++将增加该值,但返回其旧值。
所以在这种情况下:
static void Main(string[] args) { int x = 10; x = x++; Console.WriteLine(x); }
你在11处有X,然后回到10,因为10是(x ++)的返回值。
你可以改为做同样的结果:
static int plusplus(ref int x) { int xOld = x; x++; return xOld; } static void Main(string[] args) { int x = 10; x = plusplus(x); Console.WriteLine(x); }
另外值得一提的是,如果你愿意的话,你会得到11的预期结果:
static void Main(string[] args) { int x = 10; x = ++x; Console.WriteLine(x); }
在赋值x = x++
, 首先提取x = x++
的旧值,用于计算右侧expression式,在本例中为x。 然后,将x
递增1.最后,通过赋值语句将expression式求值(10)的结果赋值给x
。
也许一个相同的代码会使困境清楚:
var tmp = x; x++; x = tmp;
这相当于C#中的x = x++
代码。
x ++的行为是增加x,但在增量之前返回值。 由于这个原因,它被称为后期增量。
所以x = x ++; 简单地把意志
1.返回值 ,然后
然后增加x
3.将x的原始值(在步骤1中返回)分配给x 。
x = ++ x
将等于11。
x++;
做以下事情:
int returnValue = x; x = x+1; return returnValue;
正如你所看到的,原始值被保存,x被增加,然后原始值被返回。
结果是把值10保存在某个地方,设置x等于11,然后返回10,这导致x被设置回10.注意,x在几个周期内实际上变为11(假设没有编译器优化) 。
这不直接回答这个问题,但为什么在世界上任何人都会使用
x = x++;
?
这完全违背了后增加/预增加运算符的目的。
你可以这样想:
int x = 10;
X是一个容器,包含一个值10。
x = x++;
这可以分解为:
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中包含的值
Console.WriteLine(x);
而且,毫不奇怪,它打印出10。
根据定义,x ++返回x的值,然后递增x。
http://blogs.msdn.com/lucabol/archive/2004/08/31/223580.aspx
你做的第一件事就是所谓的“后期增量”
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 ++;
问题,是依赖于行还是在语句上,意思是说在它之后会增加; ?
尝试调用++ x,看看是否有效。
将增量运算符放在variables后面意味着在计算expression式之后发生增量和赋值…因此原始语句x = x ++; 转换为1.评估x和存储在瞬变存储器中的值…现在执行由++运算符调用的代码….(步骤2和3)2. x的递增值(在瞬态存储器中)3.分配递增值到x的存储位置…现在,继续行的其余部分,在左边,有一个=符号… 5.因此,将在步骤1中存储的值(未增值)分配给=符号左边的expression式。这是x
也许我是不对的,但是我更容易理解类似例子的结果:
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 ++一步一步:
- 计算机取x的值并将其加到x的值(10 + 10 = 20)
- 计算机将结果打到临时variables(temp = 20)
- 计算机增加x(10 + 1 = 11)
- 计算机将存储在正确的侧面操作的结果存储在variablesy(20)
- 计算机取x的值并将其加到x的值(11 + 11 = 22)
- 最终的结果是:x = 22; y = 20
现在让我们回到我们的例子,并做出相同的步骤:
public static void main(String[] args) { int x = 10; x = x++; //1, 2, 3, 4 System.out.println(x); //5 }
- 计算机取x(10)的值
- 计算机将结果提供给临时variables(temp = 10)
- 计算机增加x(10 + 1 = 11)
- 计算机将正确操作的结果存储在variablesx(10)中,
- 最终的结果是:x = 10
我知道有很多答案,也是一个可以接受的答案,但我仍然会为了另一个观点而投入我的两分钱。
我知道这个问题是C#,但我认为像一个后缀运算符它没有不同的行为比C:
int main(){ int x = 0; while (x<1) x = x++; }
编译器生成的程序集(是的,我编辑它使其更具可读性)显示
... 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: ...
等价地,循环做的是这样的:
t = x x = x + 1 x = t
边注意:打开任何优化给你一些汇编结果是这样的:
... L1: jmp L1 ...
它甚至懒得存储你告诉它给x的价值!
作为一个独立的声明, x++;
既是增量又是分配。 似乎对于什么时候会发生一些混淆。 如果我们有
int x = 10; int y = (x++) + 2;
我们将得到x = 11
和y = 12
。 分配x的当前值, 然后进行x的增量和重新分配。 所以,当使用相同的variables时,
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的值赋值给x b)增加x的临时值(我猜它可能会被优化掉)c)丢掉x的临时值
如果你想要代码返回11与作业,写:
x = ++ x;
分配的结果
x = x++;
在C和C ++中是没有定义的,我也会用C#来猜测。
所以,发生的实际操作顺序取决于编译器如何决定实现它,不能保证分配或增量是否会先发生。 (这在C#中已经有了很好的定义,正如Jon Skeet在评论中指出的那样,尽pipe我现在觉得这个答案现在的价值要低很多,但是我要保留这个post,因为OP的问题和评论中的答案没有被删除。
然而,在这种情况下,似乎发生的操作顺序是:
- x的旧值(10)被保存
- x的++部分递增
- 旧值现在分配给x的分配
这样,虽然增量发生了,但是被旧值赋值所取代,从而保持x在10。
HTH