69

我对 C# 编译器如何处理前后递增和递减有点困惑。

当我编写以下代码时:

int x = 4;
x = x++ + ++x;

x之后将具有值 10。我认为这是因为预增量设置x5,这使得它5+5 评估为10。然后后增量将更新x6,但不会使用此值,因为那时10将分配给x

但是当我编码时:

int x = 4;
x = x-- - --x;

然后x将在2之后。谁能解释为什么会这样?

4

6 回答 6

55

x-- will be 4, but will be 3 at the moment of --x, so it will end being 2, then you'll have

x = 4 - 2

btw, your first case will be x = 4 + 6

Here is a small example that will print out the values for each part, maybe this way you'll understand it better:

static void Main(string[] args)
{
    int x = 4;
    Console.WriteLine("x++: {0}", x++); //after this statement x = 5
    Console.WriteLine("++x: {0}", ++x); 

    int y = 4;
    Console.WriteLine("y--: {0}", y--); //after this statement y = 3
    Console.WriteLine("--y: {0}", --y);

    Console.ReadKey();
}

this prints out

x++: 4
++x: 6
y--: 4
--y: 2
于 2011-12-20T09:27:37.810 回答
19

让我们看一下从该语句生成的 IL

IL_0002:  ldloc.0     

将 x 的值加载到堆栈中。堆栈 => (4)

IL_0003:  dup         

复制堆栈上最顶层的项目。堆栈 => (4, 4)

IL_0004:  ldc.i4.1    

将 1 压入堆栈。堆栈 => (1, 4, 4)

IL_0005:  sub         

减去两个最高值并将结果压入堆栈。堆栈 => (3, 4)

IL_0006:  stloc.0     

将堆栈的最高值存储回 x。堆栈 => (4)

IL_0007:  ldloc.0     

将 x 的值加载回堆栈。堆栈 => (3, 4)

IL_0008:  ldc.i4.1    

将值 1 加载到堆栈中。堆栈 => (1, 3, 4)

IL_0009:  sub         

减去两者。堆栈 => (2, 4)

IL_000A:  dup         

复制顶部值 => (2, 2, 4)

IL_000B:  stloc.0     

将最高值存储回 x。堆栈 => (2, 4)

IL_000C:  sub      

减去两个最高值。堆栈 => (2)

IL_000D:  stloc.0  

将此值存储回 x 中。x == 2

于 2011-12-20T09:41:03.750 回答
9

从您的评论中:

我认为后增量和前增量是在评估完整代码行之后/之前执行的 - 但它们是在评估表达式中每个项目之后/之前执行的。

你的误解是非常普遍的。请注意,在某些语言(如 C)中,未指定副作用何时可见,因此您的陈述在 C 中为真是合法的,但不是必需的。

在 C# 中不是这种情况;在 C#中,表达式左侧代码的副作用总是观察到在右侧代码执行之前发生(来自单个线程;在多线程场景中,所有赌注都没有。)

有关增量运算符在 C# 中的作用的更详细说明,请参见:

i++ 和 ++i 有什么区别?

我写的关于这个经常被误解的话题的文章有很多额外的链接。

于 2011-12-20T16:46:33.497 回答
6

最有趣的是,您将使用 C++.Net 编译器得到完全不同的答案。

int x = 4;
x = x++ + ++x; // x = 11
x = 4;
x = x-- - --x; // x = -1

当然,结果的差异是由不同的语义决定的——这似乎很正常。但是,尽管了解两个 .net 编译器对于这些基本事物的行为方式不同这一事实也让我感到困惑。

于 2011-12-20T12:05:34.520 回答
3

在这个例子中,

int x = 4;
x = x++ + ++x;

你可以打破它:

x = 4++; which is = 5
x = 4 + ++5; which is 4 + 6
x = 10

相似地,

int x = 4;
x = x-- - --x;

这里,

x = 4--; which is = 3
x = 4 - --3; which is 4 - 2
x = 2

简单地说,您可以说,替换 x 的当前值,但是对于每个 ++ 或 -- 从 x 中添加/减去一个值。

于 2011-12-20T09:41:40.087 回答
-1

我认为对 ++++++ 案例的解释是错误的:

命令............ x 的值

..................不明确的

诠释 x=4 ....4

x++................5(第一个和为 4)

++x.............6(第二个和为 6)

x=summand1+summand2 ..4+6=10

类似于 -- -- -- 案例的解释是

命令............ x 的值

..................不明确的

诠释 x=4 ....4

x--................3(减数为 4)

--x.............2(减数为 2)

x=减法-减数..4-2=10

于 2011-12-20T09:38:45.040 回答