C#编译器行为问题?

时间:2009-10-12 18:51:27

标签: c# compiler-construction increment unary-operator

嘿大家,在下面的代码中,d的结果应该在第二个表达式之后是什么?

        int d = 1;
        d += d++;

之后假设d为3,但是一元增量d ++似乎没有生效,d保持值为2.

这个bug有名字吗?是否存在支持C#等一元增量的其他编译器?

9 个答案:

答案 0 :(得分:34)

这不是一个错误,它的行为完全符合预期。

+ =运算符扩展为:

d = d + d++;

这意味着当结果被分配回变量时,将覆盖++运算符导致的更改。

答案 1 :(得分:16)

如果你看一下生成的IL,你会看到为什么结果是2而不是3。

IL_0000:  ldc.i4.1  // load constant 1 on evaluation stack
IL_0001:  stloc.0   // pop and store value in local 0
IL_0002:  ldloc.0   // load value of local 0 on evaluation stack
IL_0003:  ldloc.0   // repeat, stack is now 1, 1
IL_0004:  dup       // duplicate topmost value on evaluation stack, 
                    // i.e. stack is now 1, 1, 1
IL_0005:  ldc.i4.1  // load constant 1 on evaluation stack
IL_0006:  add       // add two topmost values on stack, 
                    // i.e. 1 and 1 and push result on stack
IL_0007:  stloc.0   // pop and store this value in local 0
IL_0008:  add       // add the two remaining values on the stack
                    // which again happens to be 1 and 1 and push result to stack
IL_0009:  stloc.0   // pop and store this value in local 0

换句话说:存储的最终值是1和1之和。

(上面的代码来自发布模式构建)

答案 2 :(得分:12)

如果以这种方式重写代码,则将d设置为值3:

int d = 1;
d += ++d;

请查看++ Operator文档,了解您的示例为何如此行事的说明。
摘录:

  

第二种形式是后缀增量   操作。操作的结果   是它之前的操作数的值   已增加。

正如@Guffa指出的那样,这不是一个错误,只是d操作会覆盖+=中后缀增量操作的结果。

答案 3 :(得分:4)

我经常得到关于++运算符被“破坏”的问题;几乎总是因为提问的人被用于某种语言中的工作方式,其中行为++没有明确定义,比如C ++。这是我最近写的关于这种情况的文章:

http://blogs.msdn.com/ericlippert/archive/2009/08/10/precedence-vs-order-redux.aspx

答案 4 :(得分:2)

你试过++ d吗?是不是在评估了d ++之后?

答案 5 :(得分:2)

我认为d++的行为与++d不同,但d中存储的最终结果是相同的。

答案 6 :(得分:1)

愚蠢的代码是不可预测的。我可以推荐

d += 2;

答案 7 :(得分:1)

d ++和++ d是不同的。也称为“Select Isn't Broken.

答案 8 :(得分:1)

...这就是为什么我发现post / pre-increment / decrement运算符在与其他运算符的表达式中使用时高度不可读的原因的一个例子。你描述的行为是正确的,但很难推理,导致误解和错误。

即使它更啰嗦我也会把它重写为:

int d = 1;
d += d;
++d;

请注意使用预增量运算符而不是后增量运算符,以便编译器不认为它需要保留旧值的副本。