这有效,k增量:
k = 0;
k = ( false condition here ) ? 0 : k+=1;
这有效,k增量:
k = 0;
k = ( false condition here ) ? 0 : ++k;
这不起作用,k始终为0:
k = 0;
k = ( false condition here ) ? 0 : k++;
有人能解释一下发生了什么事吗?
编辑: 我不需要其他方法来写这个。 我不在乎是否可以用更简单的方式写出来。
在for循环中,无论是i ++还是++我都能工作。 为什么这里的行为不同?
答案 0 :(得分:1)
如果你想知道幕后发生了什么,我们可以看看IL水平。在此之前,我认为值得看看xanatos建议的++运算符的使用。
无论如何,让我们来看看第二种情况下生成的IL。请看右边的评论:
int k = 0;
k = false ? 0 : ++k;
IL_0001: ldc.i4.0 // Allocate space for int k
IL_0002: stloc.0 // assign 0 to k
IL_0003: ldloc.0 // load k on top of the evaluation stack --> our stack is [k]
IL_0004: ldc.i4.1 // load value 1 at location 1 for variable k --> [k 1]
IL_0005: add // Pops and add the top two values on the evaluation stack, and push the result onto the stack. our stack is --> [1]
IL_0006: dup // Copies the current topmost value on the evaluation stack, and then pushes the copy onto the evaluation stack. which in our case is 1 --> [1 1]
IL_0007: stloc.0 // Pop the top value on the stack at location 0 (e.g. assign it to k) --> [1]
IL_0008: stloc.0 // same again, the stack is empty now --> []
IL_0009: ret
正如你所看到的,最后两个stloc.0将堆栈中的两个1分配给k。事实上,如果你考虑一下,我们有两个任务。一个用于++ k,另一个用于分配三元运算的结果。正如你所说的那样产生1.让我们看一下产生0的最后一个案例:
int k = 0;
k = false ? 0 : k++;
IL_0001: ldc.i4.0 // Allocate space for int k
IL_0002: stloc.0 // assign 0 to k
IL_0003: ldloc.0 // load k on top of the evaluation stack --> our stack is [k]
IL_0004: dup // Copies the current topmost value on the evaluation stack, and then pushes the copy onto the evaluation stack. which in our case is 1 --> [k k] in this case k is still 0!
IL_0005: ldc.i4.1 // load value 1 at location 1 for variable k --> [k k 1]
IL_0006: add // Pops and add the top two values on the evaluation stack, and push the result onto the stack. our stack is --> [k 1] // because k+1 is equal 1
IL_0007: stloc.0 // Pop the top value on the stack at location 0 (e.g. assign it to k) --> [1]
IL_0008: stloc.0 // Pop the top value on the stack at location 0 (e.g. assign it to k) but in this case k is still zero!!!!! --> []
正如您可以看到IL中的注释,两个stloc.0指令最终将k的原始值(即0)分配给k本身。这就是为什么在这种情况下你会得到0而不是1。
我没有给出你的问题的解决方案,而只是解释了如何在MSIL下面的级别处理这些“简单”操作。
希望它有所帮助。
答案 1 :(得分:0)
让我们更容易:
int x = 1;
x = x++;
// x still 1
为什么?
对于运算符优先级,首先执行++
运算符,然后执行=
赋值
让我们看一下++
。来自https://msdn.microsoft.com/en-us/library/aa691363%28v=vs.71%29.aspx
If x is classified as a variable:
x is evaluated to produce the variable
The value of x is saved.
**1 is saved**
The selected operator is invoked with the saved value of x as its argument.
**2 is produced**
The value returned by the operator is stored in the location given by the evaluation of x.
**2 is put into x**
The saved value of x becomes the result of the operation.
**1 is returned**
现在我们有了作业:x = 1
。因此,x被分配twice
,一次使用2
,一次使用1
答案 2 :(得分:0)
i++
和++i
在for循环中的工作方式不同。
请考虑以下for循环定义:
for (int i=0; i<1; ++i)
可以写成:
for (int i=0; 1 >= i ; ++i)
这相当于写作:
for (int i=0; 1 >= ++i; /*No function here that increments i*/)
在这种情况下,在比较之前执行增量,并且永远不会执行循环的内容。
现在考虑这个循环:
for (int i=0; i<1; i++)
可以写成:
for (int i=0; 1 >= i ; i++)
这相当于写作:
for (int i=0; 1 >= i++; /*No function here that increments i*/)
在这种情况下,在比较之后执行增量,并且循环的内容将被执行一次。在循环结束时,我的值为1.
您可以通过执行以下操作来测试:
int i;
for (i=0; i<1; i++)
{
Console.WriteLine("i in the loop has a value of: " + i);
}
Console.WriteLine("i after the loop has a value of: " + i);
同样的规则也适用于三元运营商。
这种情况将在将值赋值给k之前执行增量,并且k将是26:
int k=25;
k= (false) ? 0 : ++k
这种情况在将值赋给k后将执行增量,k将为25:
int k=25;
k = (false) ? 0 : k++;
k + = 1与++运算符不同,k- = 1与 - 运算符不同。 k + = 1实际上是2个简明易懂的操作:
k = k+1
首先取k的值,在内存中加1,然后将值赋回k。
所以在三元例中:
int k=25;
k = (false) ? 0 : k+=1;
k将为26.分配运算符从右到左进行评估。因此编译器将首先评估k + = 1 - 使得k 26.然后执行三元比较,然后将26分配给k。
要点:
++ / - 是特殊的运算符,在执行表达式的评估时,它会影响它。 ++ x或--x - ++或 - 将在任何比较之前进行评估。 x ++或x-- - ++或 - 将在任何比较后进行评估
答案 3 :(得分:0)
注意何时混合帖子增量和分配。当您将它们与赋值一起使用时,会出现前后增量之间的差异。
后增量(++)函数实现返回原始未触摸的输入值(它保存临时副本)并递增输入:
i = 0
i = i++
后增量++函数将作为输入i=0
并将增加它。此时i
实际上将是1
,但后增量函数会返回原始值0
,因此i
将被重新分配,最终值将为{{} 1}}
在使用i ++或++的经典for循环0
中,我不会有所作为,因为在递增时没有赋值。这个for循环可能导致您头痛而不是for(int i=0; i < val; i++ )