像i = i++
之类的东西在C和C ++中有未定义的行为,因为标量对象的值在同一个表达式中会发生两次变化而没有插入序列点。
但是我认为这些表达式在C#或Java中具有明确定义的行为,因为AFAIK对参数的评估从左到右,并且遍布序列点。
那就是说,我希望i = i++
等同于i++
。但事实并非如此。以下程序输出0
。
using System;
class Program
{
static void Main(string[] args)
{
int i = 0;
i = i++;
Console.WriteLine(i);
}
}
你能帮我理解为什么吗?
声明: 我完全清楚,无论是否定义了上述结构的行为,它们都是愚蠢的,无用的,不可读的,不必要的,不应该在代码中使用。我很好奇。
答案 0 :(得分:41)
行为在C#中定义良好,评估顺序为:
i
被评估为变量i
i
递增(现为i==1
)i
设置为0.(现在i==0
)最终结果为i==0
。
通常,您首先要创建一个表达式树。要评估它,首先评估左侧,然后评估右侧,最后评估根部的操作。递归地做。
答案 1 :(得分:18)
后增量表达式i++
的结果是i
的原始值。因此,在评估i++
后(递增i
),您将i
的旧值分配给... i
。
只需使用
i++;
)
答案 2 :(得分:16)
i = ++i
是执行您认为正在进行的操作的代码。 i++
实际上表现得有点不同。
使用i++
时,i
的值会增加,但i++
的值不是i
的新值,而是之前的值。因此,当您执行i = i++
时,您说“增加i
的值,然后将i
设置为旧值”。
答案 3 :(得分:3)
嗯,必须在分配之前评估右侧表达式。现在,i++
将评估为i
的当前值,并且i的值将随后增加1。但是,分配尚未执行,如果是,它将覆盖i
(1)的当前值,无论rhs表达式计算得到什么,在您的情况下为0。
主要区别在于++i
(预增量,在递增后评估为i
的新值)和{{ 1}}或后增量,在递增之前计算为i++
的当前值。
如果您使用i
,则右侧表达式将评估为1,从而导致i == 1.