Post-increment and Pre-increment concept?
All four answers so far are incorrect, in that they assert a specific order of events.
Believing that "urban legend" has led many a novice (and professional) astray, to wit, the endless stream of questions about Undefined Behavior in expressions.
So.
For the built-in C++ prefix operator,
++x
increments x
and produces (as the expression's result) x
as an lvalue, while
x++
increments x
and produces (as the expression's result) the original value of x
.
In particular, for x++
there is no no time ordering implied for the increment and production of original value of x
. The compiler is free to emit machine code that produces the original value of x
, e.g. it might be present in some register, and that delays the increment until the end of the expression (next sequence point).
Folks who incorrectly believe the increment must come first, and they are many, often conclude from that certain expressions must have well defined effect, when they actually have Undefined Behavior.
Pre increment and post increment
result = y++ + z-- + x++;
3 1 2 = 6
if you perform this again
result1 = y++ + z-- + x++;
4 0 3 = 7
reason
operator++
returns the original value, before incrementing the variable.
and
++operator
returns the incremented value
--
is same as above just its decrement
Pre vs Post Increment
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:
- Computation of
counter
is sequenced, which could be part of the entire RHS of the statement or just the termcounter++
. - Computation of
counter += 1
is sequenced before the next statement in the program is sequenced.
There are two things to keep in mind.
- The value of a term -- what it evaluates to in an expression.
- 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
.
prefix operator behaviour in c++ when used multiple times in a statement
Earlier iterations of C++ (and C for that matter) had the concept of sequence points, where it was guaranteed all previous "things" (like the i++
side effect of evaluating that expression) would have completed.
This was replaced at some point with more tightly described "sequencing" along the lines of:
- if
A
is sequenced beforeB
,A
will be fully done beforeB
starts. - if
A
is sequenced afterB
,A
will be not start untilB
is fully done. - if
A
andB
are indeterminately sequenced, one will complete fully before the other starts, but you won't necessarily know which one went first. - if
A
andB
are unsequenced, either may start first, and they may even overlap.
From C++20, [intro.execution]
, point 10 applies to your code:
Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced.
That means that the individual bits of that full expression may happen in any order, and even overlap, resulting in differing results to what you may think is correct.
In other words, if you want deterministic code, don't do that.
And, despite your findings that the "postfix operator seems logical, it simply updates [the] value and uses it next time [the] variable is used, even when in same statement", that is actually incorrect.
While that may happen in a particular case, the expression (a++) * (a++)
is equally as non-determinstic as (++a) * (++a)
.
If you want to guarantee the sequencing of your operations, you can use more explicit code like:
// int b = (++a) * (++a);
// with pre-increment immediately before EACH use of a:
int b = (a + 1) * (a + 2); a += 2;
// or:
int b = ++a; b = ++a * b
There are always ways to achieve the same effect with code that isn't subject to indeterminate results, in the same number of lines of code if you concern yourself with that sort of metric, albeit with two statements on a single line :-)
How the post-increment operator works exaclty. Are there some exceptions?
Isn't j=j++; equivalent to j = j; j++;
No absolutely not, and this is one of the most common misunderstandings about the pre and post increment operators.
The true equivalent of j = j++;
is
int temp = j;
++j;
j = temp;
Beginners think that the post increment happens after everything else. But it's not true. The increment happens after the value is taken, not after the rest of the statement is executed. You can see that in the code above, the value of j
is taken temp = j;
, then the increment happens ++j;
, then the value is used j = temp;
.
And as has been said several times, this code only has a defined meaning from C++17, before that it was undefined.
Related Topics
Public Data Members VS Getters, Setters
Creating an Input Stream from Constant Memory
When Should I Use _Mm_Sfence _Mm_Lfence and _Mm_Mfence
What Is a Simple Example of Floating Point/Rounding Error
How to Get Double Quotes into a String Literal
Scope Vs. Lifetime of Variable
Include Header Files Using Command Line Option
When Is Uint8_T ≠ Unsigned Char
Efficient Way of Reading a File into an Std::Vector≪Char≫
Isn't the Template Argument (The Signature) of Std::Function Part of Its Type
Convert String to Int With Bool/Fail in C++
How to Remove/Refactor a «Friend» Dependency Declaration Properly
What Does Std::Match_Results::Size Return
Same Random Numbers Every Loop Iteration
What Does It Mean When a Numeric Constant in C/C++ Is Prefixed With a 0
Why Can't I Have a Non-Integral Static Const Member in a Class