On Fri, 23 Sep 2005 11:32:51 +0300, "Oleg Kharitonov"
<kh*****@mail.ru> wrote:
Hello!
I have found an interesting thing with postfix operator ++.
What should contain the variable i after exceution the following code:
int i = 5;
i = i++;
This post is rather long so if you don't want to read all of it, just
go to the bottom and read the conclusion.
In C++ this is an expression that has undefined results. Depending on
which compiler you use and what kind of optimization switches you
apply you will get different results. This is because the C++
specification doesn't contain a strict evaluation order of arguments.
If an expression contains methods with sideeffects (like ++) it can
easily introduce undefined results.
In C# evaluation order and assignment is strictly defined:
1. = and ?: evaluates from right-to-left
2. Binary operators evaluates from left to right. a+b+c => +(+(a,b),c)
3. Paranthesises and operator precedence can be used to change
evaluation order.
4. Once the operator ordering has been handled the execution order of
the arguments is from left to right.
For example:
result = G(C(A,B),D+E+F)
becomes
result = G(C(A,B),+(+(D,E),F)
which is
t1=A
t2=B
t3=C(t1,t2)
t4=D
t5=E
t6= t4 + t5
t7= F
t8= t6 + t7
t9 = G(t3,t8)
result = t9
--------------------------------------
Now that we have that we can look at the difference between var++ and
++var.
int varPlusPlus(ref int var)
{
int temp = var;
var = var + 1;
return temp;
}
int plusPlusVar(ref int var)
{
var = var +1;
return var;
}
As you can see, i++ increases the value of i, but returns the original
value. ++i increases the value of i and returns the new value. Now
that we know this, I will show what is happening with your code step
by step.
-------------------------------------
Assuming number = 10 and we do number = number + number++;
1) We evaluate 'number' which is the far most left argument. It
evaluates to 10.
2) We evaluate 'number++'. As I showed earlier the postfix ++
instruction does two things. It evaluates to the original value which
at this time is 10. It also increases the variable 'number' which from
now on has the value 11.
3) We run the function + on the two evaluated arguments 10 and 10.
This function returns 20.
4) The variable 'number' is set to 20 by the = sign operator.
-------------------------------------
To show, the importance of knowing that c# is evaluated left-to-right
consider this similar example.
Assuming number = 10 and we do number = number++ + number;
1) We evaluate 'number++'. It evaluates to the original value which
10. It also increases the variable 'number' which from now on has the
value 11.
2) We evaluate number which now has the value 11.
3) We run the function + on the two evaluated arguments 10 and 11.
This returns 21.
4) As always the last thing that happens on a row is the = statement
which sets 'number' to 21.
Notice how the result is different because of the order of the
arguments. This is the reason why you should avoid using ++ in complex
statements. In can cause severe headache when trying to read it which
can easily be solved by just splitting up the statement on two lines.
-------------------------------------
A final example with the prefix ++ statement.
Assuming number = 10 and we do number = ++number + ++number;
1) We evaluate the left most '++number'. It increases 'number' to 11
and returns 11.
2) We evaluate the right '++number'. It increases 'number' to 12 and
returns 12.
3) 11 + 12 = 23.
4) 'number' equals 23
I hope anyone that has read this far will have come to the same
conclusion as I have. Subexpressions with side effects should be
avoided as much as possible because it is way to easy to confuse even
a good programmer.
--
Marcus Andrén