Postfix increment

  • Thread starter Thread starter Oleg Kharitonov
  • Start date Start date
O

Oleg Kharitonov

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++;

In VC++ 7.1 and VC++ 2005 beta 2 the variable i contains 6.
But in C# 7.1 and C# 2005 beta 2 the variable i contains 5.

Is it behaviour correct? Can anyone explain what is the correct result?

Best regards,
Oleg.
 
Hello

Hmmm, it looks really strange. I've tested it on C++ and C# (VS 2003) and
got different result.

I was expecting to get 6 in C#, but gave me 5 !

So, it looks like it we have the next algorithm:
t = i; // some temp variable or register
i++; // here we get i=6;
i=t; // here we get back i=5

Very strange !!!
 
Interesting remark :)

But I have a question on your remark ... VC++ with managed or unmanaged
code ? I can speculate on the unmanaged situation ...
 
Oleg Kharitonov said:
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++;

In VC++ 7.1 and VC++ 2005 beta 2 the variable i contains 6.
But in C# 7.1 and C# 2005 beta 2 the variable i contains 5.

Is it behaviour correct? Can anyone explain what is the correct result?

Best regards,
Oleg.
The behavior of C# is correct, the behavior of C++ is incorrect.
From C++ reference:
It is important to note that a postfix increment or decrement expression
evaluates to the value of the expression prior to application of the
respective operator.

From C# reference about postfix increment:
The result of the operation is the value of the operand before it has been
incremented.

So the return value of i++ in the example is 5 not 6.
 
Tasos said:
Interesting remark :)

But I have a question on your remark ... VC++ with managed or unmanaged
code ? I can speculate on the unmanaged situation ...

I've checked - on both...

£ukasz
 
Here is IL code produced from C# version of that interesting code.
So, we can see, that out "i" variable receives value of 6, but then again a
value of 5.

IL_0000: ldc.i4.5
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: dup
IL_0004: ldc.i4.1
IL_0005: add
IL_0006: stloc.0
IL_0007: stloc.0
 
The postfix operator on C++ is evaluated after the expression is
evaluated (thus first we have i=5 and then i++) .

But as = and ++ are operators themselves I conjecture that there is a
precedence issue with ++ over =. Thus 5++ is evaluated first.

I checked the C++ Specification and ++ has higher priority than = ...

C# returns the appropriate result.

I thought that there might be a different implementation between
managed/unmanaged C++ implementation but there seems to be no rational
reason for that :)

What do you think about the precedence issue ?
 
The behavior of C# is correct, the behavior of C++ is incorrect.
From C++ reference:
It is important to note that a postfix increment or decrement expression
evaluates to the value of the expression prior to application of the
respective operator.

Thank you, Christof. I finally understood how this code should be executed:

1. Evaluating the value of "i++". Result is 5 becuse this is postfix ++.
2. Operator ++ has precedence over =, so i is being incrementing. Now i ==
6,
but _the result of right hand expression_ == 5.
3. i is assigning the result of right hand expression, which is 5. Now i is
5 again.

It seems to C++ compiler's bug...

Best regards,
Oleg.
 
Oleg Kharitonov said:
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++;

In VC++ 7.1 and VC++ 2005 beta 2 the variable i contains 6.
But in C# 7.1 and C# 2005 beta 2 the variable i contains 5.

Is it behaviour correct? Can anyone explain what is the correct result?

Best regards,
Oleg.

The correct behavior is for the compiler to wipe out your harddrive and call you names, so as to
prevent you from writing any code that bad again. :^)

In C/C++ the behavior of
[ i = i++ ; ]
is undefined.

I have not found anywhere in the C# standard where they discuss sequence points yet.
So it is possible that this behavior is "Defined" in C#.

It should, however, be avoided at all costs

Bill
 
Oleg Kharitonov said:
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++;

In VC++ 7.1 and VC++ 2005 beta 2 the variable i contains 6.
But in C# 7.1 and C# 2005 beta 2 the variable i contains 5.

Is it behaviour correct? Can anyone explain what is the correct result?

Best regards,
Oleg.

The correct behavior is for the compiler to wipe out your harddrive and
call you names, so as to prevent you from writing any code that bad again.
:^)

In C/C++ the behavior of
[ i = i++ ; ]
is undefined.

I have not found anywhere in the C# standard where they discuss sequence
points yet.
So it is possible that this behavior is "Defined" in C#.

It should, however, be avoided at all costs

Bill

It's clearly defined in the C# standard. There's no reason to avoid it. If
it is undefined in C++, then it should be avoided in C++.

Pete
 
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.
 
Pete Davis said:
It's clearly defined in the C# standard. There's no reason to avoid it.

Just because behaviour is well-defined doesn't mean it shouldn't be
avoided. The fact that some people on this thread expected one answer
but got another makes it clear that it's not obvious what it does -
*that's* why it should be avoided.
 
It's clearly defined in the C# standard. There's no reason to avoid it.
Just because behaviour is well-defined doesn't mean it shouldn't be
avoided. The fact that some people on this thread expected one answer
but got another makes it clear that it's not obvious what it does -
*that's* why it should be avoided.

Actually, I regretted the post right after I made it. You are correct. I
find it very annoying when C/C++ programmers take advantage of very obscure,
hard to decipher constructs for this same reason.

Pete
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top