7

I get the basis for the pre and post increment, but having trouble wrapping my mind when it actually takes place on a post increment.

For example in the following post increment code:

int counter = 10;
int result = 0;

result = counter++ + 10;

cout << "Counter: " << counter << endl;
cout << "Result: " << result << endl;

I understand that Counter will come out as 11 and result at 20. Is Result coming out at 20 because the entire function is being run, and THEN it is adding +1 when the program goes to return 0; ?

When exactly is that +1 getting added?

Thanks

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Tman
  • 389
  • 1
  • 14

3 Answers3

6

When exactly is that +1 getting added?

According to the standard:

The value computation of the ++ expression is sequenced before the modification of the operand object.

From a layman's point of view:

  1. Computation of counter is sequenced, which could be part of the entire RHS of the statement or just the term counter++.
  2. Computation of counter += 1 is sequenced before the next statement in the program is sequenced.

There are two things to keep in mind.

  1. The value of a term -- what it evaluates to in an expression.
  2. The side effects of the evaluation of the term.

In the case of counter++:

The value of the term is the value of counter before it is incremented.
The side effect of evaluation of the term is incrementing of the value of counter.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • 4
    I don't think it has to be immediately after the value computation. As far as I know, it could happen after the assignment. – eesiraed May 17 '19 at 05:17
4

Also for a better understanding you can consider these loosely described examples:

  • think of the pre-increment for the_object of the_type as a function like this:
the_object = the_object + 1;
return the_object;
  • now think of the Post-increment for the_object of the_type as a function like this:
the_type backup_of_the_object;
backup_of_the_object = the_object;
the_object = the_object + 1;
return backup_of_the_object;

Now consider:

result = counter++ + 10;

When the program is being compiled:

  1. compiler sees result = at the beginning of the line, so it should first determine what is placed at the right side of = and then produce the machine code to assign it to the left side of = which is result.
  2. compiler sees counter but the statement has not ended because; has not been reached yet. So now it knows that it also has to do something with counter.
  3. compiler sees ++ but the statement has not ended. So now it knows that it has to consider producing the machine code to perform counter++ first.

  4. compiler sees +. So now it knows that it has to consider producing the machine code to add the right side of + and the left side of + which was counter++.

  5. compiler sees 10; and finally the statement has ended. So now it knows all that it needed to know! It knows that after producing the machine code to perform counter++, it should produce the machine code to add 10 to the outcome_of it. Then it should produce the machine code to assign the outcome_of that to the result.

when the program is running:

  1. CPU should perform counter++

now counter is incremented by 1 hence it is 11 but the outcome_of(counter++) is the previous value of the counter which is 10

  1. CPU should perform outcome_of(counter++) + 10

now outcome_of(outcome_of(counter++) + 10) is outcome_of(10 + 10) which is 20

  1. CPU should perform result = outcome_of(outcome_of(counter++) + 10)

now result is 20

Also please note that every stages that was described was only about
result = counter++ + 10;
regardless of what is going to happen afterwards. Meaning before

cout << "Counter: " << counter << endl;
cout << "Result: " << result << endl;

so obviously before main() returns 0.

In my opinion you should take it easy and learn it through experience by writing and running some programs!

Good luck!

AKL
  • 1,367
  • 7
  • 20
3

Post-increment operator: A post-increment operator is used to increment the value of variable after executing expression completely in which post increment is used. In the Post-Increment, value is first used in an expression and then incremented.

So in your case

result = counter++ + 10;

post increment takes place after it has been used in this statement, and obviously it is reflected in next statement.

Tejendra
  • 1,874
  • 1
  • 20
  • 32
  • The incrementation is guaranteed to be after the value computation but not necessarily after the entire expression is evaluated. For example, it could be done either before or after `result` is changed. – eesiraed May 17 '19 at 05:14
  • 1
    This would make `foo(i++);`, which is UB, defined. – Kostas May 17 '19 at 05:16
  • @Kosta Well there are some cases which are undefined, check [here](https://stackoverflow.com/questions/949433/why-are-these-constructs-using-pre-and-post-increment-undefined-behavior) – Tejendra May 17 '19 at 05:20
  • 1
    @FeiXiang Side effects of evaluation of arguments are unsequenced. See [this](https://stackoverflow.com/questions/11060968/using-the-post-increment-in-function-arguments) – Kostas May 17 '19 at 05:21
  • @Kosta That's UB because `x` is used in both of the two arguments, one of which is an expression that modifies `x`. So the side effect of the `x++` in the second argument is unsequenced relative to the value computation of `x` in the first argument. Your function only has a single argument, so that doesn't apply here. The value computation and side effects of any function argument are sequenced before the execution of any statement in the function, so even if you read/modify `i` in the function it's still not UB. (Accidentally deleted my first comment) – eesiraed May 17 '19 at 05:26