views:

450

answers:

10

Hey everyone, in the following code, what should the result of d be after the second expression?

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

One would assume d is 3 afterwards but the unary increment d++ doesn't seem to take effect and d retains a value of 2.

Is there a name for this bug? Does it exist for other compilers that support unary increment like C#?

+12  A: 

If you rewrite your code this way, it will set d to have a value of 3:

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

Take a look at the ++ Operator documentation for an explanation as to why your example behaves the way it does.
Excerpt:

The second form is a postfix increment operation. The result of the operation is the value of the operand before it has been incremented.

As @Guffa pointed out, it's not a bug, it's simply that the result of your postfix increment operation in d is being overwritten by the += operation.

Donut
I think there is a hole in your donut. Different question?
kenny
if anyone *re-wrote* their code to look this way, I would fire them from the team immediately. 2 strikes and all.
Cheeso
+2  A: 

Have you tried ++d? Isn't d++ evaluated after?

wsorenson
Be careful. Evaluated after *what*, exactly? The chief difference between ++d and d++ is that the evaluation of the result of the expression happens either before or after the *storage* of the incremented result into the variable. It is a common error to believe that the evaluation of the postfix expression *as a whole* somehow happens "later" than other parts of the expression in which it is embedded, but this is a myth.
Eric Lippert
Right. If the ++ was applied after the entire expression was evaluated, then we would expect to see 3.
wsorenson
+34  A: 

It's not a bug, it acts exactly as expected.

The += operator expands into this:

d = d + d++;

That means that the change that the ++ operator causes is overwritten when the result is assigned back to the variable.

Guffa
the full expansion would be: temp = d + d; d = d + 1; d = temp;
JustSmith
I think his issue is with the d++, not the +=.
Eclipsed4utoo
+2  A: 

I think d++ is different than ++d.

L. Moser
+1  A: 

Silly code is unpredictable. Might I recommend

d += 2;
David B
It's not unpredictable at all. The language specification is very clear about what this code should do. I agree it's silly though.
Jon Skeet
not "unpredictable", but definitely "needlessly hard to predict", which I think is close enough. :)
jalf
+1  A: 

d++ and ++d are different. Also known as "Select Isn't Broken."

JesperE
+1  A: 

...and this would be an example of the reason why I find the post/pre- increment/decrement operators to be highly unreadable when used in an expression with other operators. The behavior you describe is correct, but hard to reason about, leading to misunderstandings and bugs.

Even though it's wordier I would rewrite this as:

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

Note the use of the pre-increment operator instead of the post-increment so that the compiler doesn't think it needs to keep a copy of the old value.

tvanfosson
+15  A: 

If you take a look at the generated IL, you'll see why the result is 2 and not 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

In other words: The final value stored is the sum of 1 and 1.

(the code above is from release mode build)

Brian Rasmussen
+1 for taking the effort to analyse it at the IL level. :)
Noldorin
+3  A: 

I frequently get questions about the ++ operators being "broken"; almost always it is because the person asking the question is used to the way it works in some language where behaviour ++ is not well-defined, like C++. Here's a recent article I wrote about such a scenario:

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

Eric Lippert