请问您能帮助我理解为什么变量a
在第一种情况下没有增加但是在第二种情况下会增加?
案例1:
int a = 10;
a = a++;
Console.WriteLine(a); //prints 10
案例2:
int a = 10;
int c = a++;
Console.WriteLine(a); //prints 11
我已经解决了其他类似的问题,但找不到任何细节。
更新1:我认为程序如何流动
案例1:
1. 'a' is assigned 10
2. 'a' is assigned 10 before increment happens
3. 'a' is incremented by 1 (Why doesn't this step affect the final value of 'a'?)
4. 'a' is printed --> 10
案例2:
1. 'a' is assigned 10
2. 'c' is assigned 10 before 'a' is incremented
3. 'a' is incremented by 1 (Why does the increment of 'a' work here?)
4. 'a' is printed --> 11
更新2:感谢所有答案,我想我已经理解了,如果我错了请纠正我。
案例1:
1. `a` is assigned 10
2. Compiler evaluates `a++`, stores old value 10 and new value 11 as well. Since it's a post increment operation, assigns the old value to `a`. What i thought was, compiler would assign the old value 10 first and evaluate the `++` operation later. This is where i was wrong, compiler evaluates the RHS beforehand and assigns the value based on the operator.
4. 'a' is printed --> 10
案例2:
1. `a` is assigned 10
2. Compiler evaluates `a++`, stores old value 10 and new value 11 as well. Since it's a post increment operation, assigns the old value to `c` but value of `a` is preserved with `11`.
4. 'a' is printed --> 11
答案 0 :(得分:6)
第一种情况a = a++
是后增量。这表示将{1}添加到a
,但返回先前的a
值,然后将之前的结果存储回a
。这基本上是一种无操作。
如果是预增量a = ++a
,那么a
将为11.
答案 1 :(得分:5)
对我而言,理解某些行为的最佳方法是检查IL生成。在你的第一种情况下它是
IL_0001: ldc.i4.s 0A // stack: 10
IL_0003: stloc.0 // a = 10, stack: empty
IL_0004: ldloc.0 // stack: 10
IL_0005: dup // stack: 10, 10
IL_0006: ldc.i4.1 // stack: 10, 10, 1
IL_0007: add // stack: 10, 11
IL_0008: stloc.0 // a = 11, stack: 10
IL_0009: stloc.0 // a = 10, stack: empty
IL_000A: ldloc.0 // stack: 10
IL_000B: call System.Console.WriteLine
您可以看到堆栈上仍然存在原始值,因此创建的11最终会被覆盖。
让我试着用简单的语言解释它。
当您为变量(a = a++
)赋值时,首先会对赋值的整个右侧进行求值,以保证正确的值,即它是如何的。所以没有你得到10,应用程序继续执行下一行时增加值。
现在,想象一下后增量作为某人,他先增加一个值,但给了他的世界,你将从表达式中获得原始值。现在你应该明白为什么11被覆盖了。增量先行,最后,你得到承诺原始价值(正如IL证明的那样)。
答案 2 :(得分:3)
这里没有任何未定义的行为,因为有人在评论中描述。
这是明确定义的行为。要了解发生的情况,您必须首先了解pre increment and post increment运算符的工作原理。
<强>情况1:强>
a++
(增量后)将增加a
的值并将其存储在a
中,然后在值递增之前返回该值。
因此,在执行a++;
后,a
的值将为11
,但运算符将返回10
。
然后a = a++;
分配部分变为a = 10;
。
<强>情况2:强>
Sameway a++;
会将a
的值增加到11
并返回之前的值(10)。将分配给c
。 c
为10,a
为11,因为在这种情况下,您不会覆盖a
的值。
您的案例1 等于:
int a = 10;
int temp = a;//10
a = a + 1; //11
a = temp; //10
Console.WriteLine(a);//10
和 Case2 等于:
int a = 10;
int temp = a;//10
a = a + 1; //11
int c = temp;//10
Console.WriteLine(a);//11
我希望现在应该清楚为什么你看到你所看到的。
答案 3 :(得分:2)
这不是未定义的行为,也不是错误。来自MSDN Documentation:
The increment operator (++) increments its operand by 1.
The increment operator can appear before or after its operand.
The first form is a prefix increment operation. The result of the operation is the value of the operand after it has been incremented.
The second form is a postfix increment operation. The result of the operation is the value of the operand before it has been incremented.
从字面上看,MSDN告诉你,如果你使用这种语法(后缀):
a = a++;
然后,操作结果将a
分配给a
然后递增。但是,由于已经进行了赋值操作,因此您将丢失增量的结果。
像这样使用它(前缀):
a = ++a;
这将首先递增a
,然后将递增的值指定为a
。
修改强>
我会试着打破这个,所以希望你能更好地理解。
首先,要知道++
总是返回一个值。如果您使用前缀版本(例如++a
),则会返回a+1
的值。如果您使用后缀版本(例如a++
),则会在增量发生之前返回a
的值。
执行此代码时:
int a = 10;
a = a++;
您告诉编译器在增量之前为a
赋值a
。因此a
在执行此操作后等于10
。增量值11
在“下面”中丢失。请注意,您没有将11
分配给a
。您在增量之前分配旧值,这就是您获得10
输出的原因。
执行此代码时:
int a = 10;
int b = a++;
在最后一行执行后,它将a
增加到等于11
并将10
分配给'b'。由于您要分配给另一个变量,因此a
不会像第一个示例中那样被原始值10
覆盖。
为了使这更加直观,请看这里:
a = a++;
^ a is increased to 11, but the postfix increment returns the old value (10)
这条线有效地成为:
a = 10;
int b = a++;
^ a is increased to 11, but b gets assigned a's old value
这条线有效地成为:
int b = 10;
a = a + 1;
这清楚了吗?
答案 4 :(得分:0)
为清楚起见,++ a和++之间存在不同。
它们中的两个产生相同的结果,即将 a 增加1,但是该过程略有不同,只能通过将其分配给另一个变量来看到它。
您可能正在寻找 pre 和 post 增量之间的差异
案例1
int a,b;
a = 10;
b = a++; //Here b is assigned by a post-incremented a, therefore b value is still 10
案例2
int a,b;
a = 10;
b = ++a; //Here b is assigned by a pre-incremented a, b value is now 11
取自http://en.wikipedia.org/wiki/Increment_and_decrement_operators
<强>更新强>
回答此问题
int a = 10;
a = a++;
过程如下:
<强> 1。变量&#39; a&#39;创建数据类型为整数
<强> 2。变量&#39; a&#39;值分配为10
第3。检查右侧的可用性和数据类型的正确性。这意味着正在执行右侧的所有操作(增量&#39; a&#39;)。 &#39;一个&#39;现在是11
<强> 4。将增加后的值分配给&#39; a&#39;,即10,&#39; a&#39;现在是10
答案 5 :(得分:0)
我不认为这是一种未定义的行为,因为在第一种情况下:
int a = 10;
a = a++;
Console.WriteLine(a); //prints 10
a
的值是增量操作之前的值,这意味着如果我们简化a = a++
,那么:
a = a ; // `a` has `10`
a++; // `a` has `11`
然后只有a
的值为11
。
第二种情况:
int a = 10;
int c = a++;
Console.WriteLine(a); //prints 11
现在c
的值为10
,因为赋值操作使得左侧的值在增量操作之前获取变量的值(在右侧),然后才右侧的值上升1
。
答案 6 :(得分:-1)
你应该在案例2中打印出来。 post incement运算符结果始终是递增前的值。因此,首先将值10返回,然后将其递增为11,然后将运算符结果(10)赋值给左操作数。