Post-Increment Within a Self-Assignment

Post-increment within a self-assignment

Let’s take a look at the intermediary language code for that:

IL_0000:  nop
IL_0001: ldc.i4.s 2A
IL_0003: stloc.0 // c
IL_0004: ldloc.0 // c

This loads the constant integer 42 onto the stack, then stores it into the variable c, and loads it immediately again onto the stack.

IL_0005:  stloc.1
IL_0006: ldloc.1

This copies the value into another register, and also loads it again.

IL_0007:  ldc.i4.1
IL_0008: add

This adds the constant 1 to the loaded value

IL_0009:  stloc.0     // c

… and stores the result (43) into the variable c.

IL_000A:  ldloc.1
IL_000B: stloc.0 // c

Then the value from the other register is loaded (that’s still 42!) and stored into the variable c.

IL_000C:  ldloc.0     // c
IL_000D: call System.Console.WriteLine
IL_0012: nop
IL_0013: ret

Then the value (42) is loaded from the variable, and printed.


So what you can see from this is that while c++ increments the variable by one after the result was returned, that incrementing happens still before assinging the value to the variable. So the sequence is more like this:

  1. Get value from c
  2. Post-increment c
  3. Assign previously read value to c

And that should explain why you get that result :)


To add one more example, since this was mentioned in a comment that was since deleted:

c = c++ + c;

This works very similarly: Assuming an initial value of 2 again, the left side of the addition is evaluated first. So the value is read from the variable (2), then c is incremented (c becomes 3). Then the right side of the addition is evaluated. The value of c is read (now 3). Then the addition takes place (2 + 3) and the result (5) is assigned to the variable.


The takeaway from this is that you should avoid mixing increment and decrement operations in normal expressions. While the behavior is very well defined and makes absolute sense (as shown above), it is still sometimes difficult to wrap your head around it. Especially when you assign something to the same variable that you increment in the expression, this becomes confusing quickly. So do yourself and others a favor and avoid increment/decrement operations when they are not completely on their own :)

Assignment along with Post increment

The order in which x = x++ is executed is as follows:

  • Old value of x is calculated (oldValue = 1)
  • New value for x is calculated by adding 1 to old value (newValue = 2)
  • New value is assigned to x. At this point x becomes 2!
  • Old value is returned (return value is 1). This concludes the evaluation of x++
  • The old value is assigned to x. At this point x becomes 1

The above rules are described here. The rules indicate that x is incremented before assignment, not after.

Why can't a++ (post-increment operator) be an Lvalue?

And As per rule of post increment the value of variable a will increment only after execution of that statement.

That's a bit misleading. The variable is incremented immediately. But the result of the expression is the old value. This should make it easier to understand why it cannot be an lvalue. The modified object doesn't have the old value, so the hypothetical lvalue cannot refer to that object. The value is a new, temporary object; it is a prvalue.

As an analogy, think about writing a function that does the same thing as post increment. This is how it would be written (if you define overloaded operator overload for a class, then a function such as this is quite literally what you'd write with a few changes):

int post_increment(int& operand)
{
int old = operand;
operand += 1;
return old;
}

How could you meaningfully re-write that function to return an lvalue (reference) and still have the behaviour expected from the post increment?

Java increment and assignment operator

No, the printout of 10 is correct. The key to understanding the reason behind the result is the difference between pre-increment ++x and post-increment x++ compound assignments. When you use pre-increment, the value of the expression is taken after performing the increment. When you use post-increment, though, the value of the expression is taken before incrementing, and stored for later use, after the result of incrementing is written back into the variable.

Here is the sequence of events that leads to what you see:

  • x is assigned 10
  • Because of ++ in post-increment position, the current value of x (i.e. 10) is stored for later use
  • New value of 11 is stored into x
  • The temporary value of 10 is stored back into x, writing right over 11 that has been stored there.

C++17 sequencing: post-increment on left side of assignment

And the question: is the warning erroneous?

It depends.

Technically, the code in question is well-defined. The right-hand side is sequenced before the left-hand side in C++17, whereas before it was indeterminately sequenced. And gcc compiles the code correctly, v[0] == 1 after that assignment.

However, it is also terrible code that should not be written, so while the specific wording of the warning is erroneous, the actual spirit of the warning seems fine to me. At least, I'm not about to file a bug report about it and it doesn't seem like the kind of thing that's worth developer time to fix. YMMV.

Post-increment vs Assignment in C++ operation precedence table

"Precedence" is misleading. It has little to do in general with evaluation order (what happens first), but instead determines what is the operand of each operator for the purpose of evaluation. But let's examine your example.

*(b++) = 5;

This means that 5 is to be assigned to the lvalue on the left. And since C++17, we know that 5 is evaluated entirely before *(b++). Prior to that, they could be evaluated in any order.

Now, b++ has the meaning of "increment b, but evaluate to its previous value". So b++ may cause the increment to happen prior to the assignment taking place, yes, but the value of (b++) is the address before the increment happened. And that is why b is updated to point at the next element, while modifying the current one, in one expression.



Related Topics



Leave a reply



Submit