i = i++ doesn't increment i. Why? [duplicate] - c#

This question already has answers here:
Closed 11 years ago.
Possible Duplicates:
Why does this go into an infinite loop?
Things like i = i++ have undefined behavior in C and C++ because the value of a scalar object is changes twice within the same expression without intervening sequence point.
However I suppose that these kind of expressions have well-defined behavior in C# or Java because AFAIK the evaluation of argument goes left to right and there are sequence points all over.
That said, I'd expect i = i++ to be equivalent to i++. But it's not. The following program outputs 0.
using System;
class Program
{
static void Main(string[] args)
{
int i = 0;
i = i++;
Console.WriteLine(i);
}
}
Could you help me understand why?
Disclaimer:
I am fully aware that whether or not the behavior of above-mentioned constructs is defined, they are silly, useless, unreadable, unnecessary and should not be used in code. I am just curious.

The behavior is well defined in C# and the evaluation order is:
Left side i is evaluated to the variable i
Right side is evaluated to 0, and i is incremented (now i==1)
The assignment is executed, it sets i to 0. (now i==0)
The end result is i==0.
In general you first create an expression tree. To evaluate it you evaluate first the left side, then the right side and finally the operation at the root. Do that recursively.

The result of the post-increment expression i++ is the original value of i. So after i++ has been evaluated (incrementing i), you assign the old value of i to ... i.
Just use
i++;
;)

i = ++iis the code that does what you think is going on here. i++ actually behaves a bit differently.
With i++, the value of i is increased, but the value of i++ is not the new value of i, it's the previous value. So when you do i = i++, you're saying "increase the value of i, then set i to the old value".

Well, the right-hand side expression must be evaluated before the assignment can take place. Now, i++ will evaluate to the current value of i, and i's value will subsequently increase by one. However, the assignment hasn't been performed yet, and when it is, it will overwrite the current value of i (1) with whatever the rhs expression evaluated to, which in your case was 0.
The key difference is between ++i (pre-increment, which evaluates to the new value of i after incrementing) and i++, or post-increment, which evaluates to the current value of i before incrementing.
Had you used ++i instead, the right-hand side expression would have evaluated to 1, resulting in i == 1.

Related

Why does incrementation take place after setter in this example? [duplicate]

I've seen them both being used in numerous pieces of C# code, and I'd like to know when to use i++ and when to use ++i?
(i being a number variable like int, float, double, etc).
The typical answer to this question, unfortunately posted here already, is that one does the increment "before" remaining operations and the other does the increment "after" remaining operations. Though that intuitively gets the idea across, that statement is on the face of it completely wrong. The sequence of events in time is extremely well-defined in C#, and it is emphatically not the case that the prefix (++var) and postfix (var++) versions of ++ do things in a different order with respect to other operations.
It is unsurprising that you'll see a lot of wrong answers to this question. A great many "teach yourself C#" books also get it wrong. Also, the way C# does it is different than how C does it. Many people reason as though C# and C are the same language; they are not. The design of the increment and decrement operators in C# in my opinion avoids the design flaws of these operators in C.
There are two questions that must be answered to determine what exactly the operation of prefix and postfix ++ are in C#. The first question is what is the result? and the second question is when does the side effect of the increment take place?
It is not obvious what the answer to either question is, but it is actually quite simple once you see it. Let me spell out for you precisely what x++ and ++x do for a variable x.
For the prefix form (++x):
x is evaluated to produce the variable
The value of the variable is copied to a temporary location
The temporary value is incremented to produce a new value (not overwriting the temporary!)
The new value is stored in the variable
The result of the operation is the new value (i.e. the incremented value of the temporary)
For the postfix form (x++):
x is evaluated to produce the variable
The value of the variable is copied to a temporary location
The temporary value is incremented to produce a new value (not overwriting the temporary!)
The new value is stored in the variable
The result of the operation is the value of the temporary
Some things to notice:
First, the order of events in time is exactly the same in both cases. Again, it is absolutely not the case that the order of events in time changes between prefix and postfix. It is entirely false to say that the evaluation happens before other evaluations or after other evaluations. The evaluations happen in exactly the same order in both cases as you can see by steps 1 through 4 being identical. The only difference is the last step - whether the result is the value of the temporary, or the new, incremented value.
You can easily demonstrate this with a simple C# console app:
public class Application
{
public static int currentValue = 0;
public static void Main()
{
Console.WriteLine("Test 1: ++x");
(++currentValue).TestMethod();
Console.WriteLine("\nTest 2: x++");
(currentValue++).TestMethod();
Console.WriteLine("\nTest 3: ++x");
(++currentValue).TestMethod();
Console.ReadKey();
}
}
public static class ExtensionMethods
{
public static void TestMethod(this int passedInValue)
{
Console.WriteLine($"Current:{Application.currentValue} Passed-in:{passedInValue}");
}
}
Here are the results...
Test 1: ++x
Current:1 Passed-in:1
Test 2: x++
Current:2 Passed-in:1
Test 3: ++x
Current:3 Passed-in:3
In the first test, you can see that both currentValue and what was passed into the TestMethod() extension show the same value, as expected.
However, in the second case, people will try to tell you that the increment of currentValue happens after the call to TestMethod(), but as you can see from the results, it happens before the call as indicated by the 'Current:2' result.
In this case, first the value of currentValue is stored in a temporary. Next, an incremented version of that value is stored back in currentValue but without touching the temporary which still stores the original value. Finally that temporary is passed to TestMethod(). If the increment happened after the call to TestMethod() then it would write out the same, non-incremented value twice, but it does not.
It's important to note that the value returned from both the currentValue++ and ++currentValue operations are based on the temporary and not the actual value stored in the variable at the time either operation exits.
Recall in the order of operations above, the first two steps copy the then-current value of the variable into the temporary. That is what's used to calculate the return value; in the case of the prefix version, it's that temporary value incremented while in the case of the suffix version, it's that value directly/non-incremented. The variable itself is not read again after the initial storage into the temporary.
Put more simply, the postfix version returns the value that was read from the variable (i.e. the value of the temporary) while the prefix version returns the value that was written back to the variable (i.e. the incremented value of the temporary). Neither return the variable's value.
This is important to understand because the variable itself could be volatile and have changed on another thread which means the return value of those operations could differ from the current value stored in the variable.
It is surprisingly common for people to get very confused about precedence, associativity, and the order in which side effects are executed, I suspect mostly because it is so confusing in C. C# has been carefully designed to be less confusing in all these regards. For some additional analysis of these issues, including me further demonstrating the falsity of the idea that prefix and postfix operations "move stuff around in time" see:
https://ericlippert.com/2009/08/10/precedence-vs-order-redux/
which led to this SO question:
int[] arr={0}; int value = arr[arr[0]++]; Value = 1?
You might also be interested in my previous articles on the subject:
https://ericlippert.com/2008/05/23/precedence-vs-associativity-vs-order/
and
https://ericlippert.com/2007/08/14/c-and-the-pit-of-despair/
and an interesting case where C makes it hard to reason about correctness:
https://learn.microsoft.com/archive/blogs/ericlippert/bad-recursion-revisited
Also, we run into similar subtle issues when considering other operations that have side effects, such as chained simple assignments:
https://learn.microsoft.com/archive/blogs/ericlippert/chaining-simple-assignments-is-not-so-simple
And here's an interesting post on why the increment operators result in values in C# rather than in variables:
Why can't I do ++i++ in C-like languages?
Oddly it looks like the other two answers don't spell it out, and it's definitely worth saying:
i++ means 'tell me the value of i, then increment'
++i means 'increment i, then tell me the value'
They are Pre-increment, post-increment operators. In both cases the variable is incremented, but if you were to take the value of both expressions in exactly the same cases, the result will differ.
If you have:
int i = 10;
int x = ++i;
then x will be 11.
But if you have:
int i = 10;
int x = i++;
then x will be 10.
Note as Eric points out, the increment occurs at the same time in both cases, but it's what value is given as the result that differs (thanks Eric!).
Generally, I like to use ++i unless there's a good reason not to. For example, when writing a loop, I like to use:
for (int i = 0; i < 10; ++i) {
}
Or, if I just need to increment a variable, I like to use:
++x;
Normally, one way or the other doesn't have much significance and comes down to coding style, but if you are using the operators inside other assignments (like in my original examples), it's important to be aware of potential side effects.
int i = 0;
Console.WriteLine(i++); // Prints 0. Then value of "i" becomes 1.
Console.WriteLine(--i); // Value of "i" becomes 0. Then prints 0.
Does this answer your question ?
The way the operator works is that it gets incremented at the same time, but if it is before a variable, the expression will evaluate with the incremented/decremented variable:
int x = 0; //x is 0
int y = ++x; //x is 1 and y is 1
If it is after the variable the current statement will get executed with the original variable, as if it had not yet been incremented/decremented:
int x = 0; //x is 0
int y = x++; //'y = x' is evaluated with x=0, but x is still incremented. So, x is 1, but y is 0
I agree with dcp in using pre-increment/decrement (++x) unless necessary. Really the only time I use the post-increment/decrement is in while loops or loops of that sort. These loops are the same:
while (x < 5) //evaluates conditional statement
{
//some code
++x; //increments x
}
or
while (x++ < 5) //evaluates conditional statement with x value before increment, and x is incremented
{
//some code
}
You can also do this while indexing arrays and such:
int i = 0;
int[] MyArray = new int[2];
MyArray[i++] = 1234; //sets array at index 0 to '1234' and i is incremented
MyArray[i] = 5678; //sets array at index 1 to '5678'
int temp = MyArray[--i]; //temp is 1234 (becasue of pre-decrement);
Etc, etc...
Just for the record, in C++, if you can use either (i.e.) you don't care about the ordering of operations (you just want to increment or decrement and use it later) the prefix operator is more efficient since it doesn't have to create a temporary copy of the object. Unfortunately, most people use posfix (var++) instead of prefix (++var), just because that is what we learned initially. (I was asked about this in an interview). Not sure if this is true in C#, but I assume it would be.
I think I'll try answering the question using code. Imagine the following methods for, say, int:
// The following are equivalent:
// ++i;
// PlusPlusInt(ref i);
//
// The argument "value" is passed as a reference,
// meaning we're not incrementing a copy.
static int PlusPlusInt(ref int value)
{
// Increment the value.
value = value + 1;
// Return the incremented value.
return value;
}
// The following are equivalent:
// i++;
// IntPlusPlus(ref i);
//
// The argument "value" is passed as a reference,
// meaning we're not incrementing a copy.
static int IntPlusPlus(ref int value)
{
// Keep the original value around before incrementing it.
int temp = value;
// Increment the value.
value = value + 1;
// Return what the value WAS.
return temp;
}
Assuming you know how ref works, this should clear this up really nicely. Explaining it in english is a lot more clunky in my opinion.

Pointer arithmetic difference in C# and Visual C++ [duplicate]

What are "sequence points"?
What is the relation between undefined behaviour and sequence points?
I often use funny and convoluted expressions like a[++i] = i;, to make myself feel better. Why should I stop using them?
If you've read this, be sure to visit the follow-up question Undefined behavior and sequence points reloaded.
(Note: This is meant to be an entry to Stack Overflow's C++ FAQ. If you want to critique the idea of providing an FAQ in this form, then the posting on meta that started all this would be the place to do that. Answers to that question are monitored in the C++ chatroom, where the FAQ idea started out in the first place, so your answer is very likely to get read by those who came up with the idea.)
C++98 and C++03
This answer is for the older versions of the C++ standard. The C++11 and C++14 versions of the standard do not formally contain 'sequence points'; operations are 'sequenced before' or 'unsequenced' or 'indeterminately sequenced' instead. The net effect is essentially the same, but the terminology is different.
Disclaimer : Okay. This answer is a bit long. So have patience while reading it. If you already know these things, reading them again won't make you crazy.
Pre-requisites : An elementary knowledge of C++ Standard
What are Sequence Points?
The Standard says
At certain specified points in the execution sequence called sequence points, all side effects of previous evaluations
shall be complete and no side effects of subsequent evaluations shall have taken place. (§1.9/7)
Side effects? What are side effects?
Evaluation of an expression produces something and if in addition there is a change in the state of the execution environment it is said that the expression (its evaluation) has some side effect(s).
For example:
int x = y++; //where y is also an int
In addition to the initialization operation the value of y gets changed due to the side effect of ++ operator.
So far so good. Moving on to sequence points. An alternation definition of seq-points given by the comp.lang.c author Steve Summit:
Sequence point is a point in time at which the dust has settled and all side effects which have been seen so far are guaranteed to be complete.
What are the common sequence points listed in the C++ Standard?
Those are:
at the end of the evaluation of full expression (§1.9/16) (A full-expression is an expression that is not a subexpression of another expression.)1
Example :
int a = 5; // ; is a sequence point here
in the evaluation of each of the following expressions after the evaluation of the first expression (§1.9/18) 2
a && b (§5.14)
a || b (§5.15)
a ? b : c (§5.16)
a , b (§5.18) (here a , b is a comma operator; in func(a,a++) , is not a comma operator, it's merely a separator between the arguments a and a++. Thus the behaviour is undefined in that case (if a is considered to be a primitive type))
at a function call (whether or not the function is inline), after the evaluation of all function arguments (if any) which
takes place before execution of any expressions or statements in the function body (§1.9/17).
1 : Note : the evaluation of a full-expression can include the evaluation of subexpressions that are not lexically
part of the full-expression. For example, subexpressions involved in evaluating default argument expressions (8.3.6) are considered to be created in the expression that calls the function, not the expression that defines the default argument
2 : The operators indicated are the built-in operators, as described in clause 5. When one of these operators is overloaded (clause 13) in a valid context, thus designating a user-defined operator function, the expression designates a function invocation and the operands form an argument list, without an implied sequence point between them.
What is Undefined Behaviour?
The Standard defines Undefined Behaviour in Section §1.3.12 as
behavior, such as might arise upon use of an erroneous program construct or erroneous data, for which this International Standard imposes no requirements 3.
Undefined behavior may also be expected when this
International Standard omits the description of any explicit definition of behavior.
3 : permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or with-
out the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).
In short, undefined behaviour means anything can happen from daemons flying out of your nose to your girlfriend getting pregnant.
What is the relation between Undefined Behaviour and Sequence Points?
Before I get into that you must know the difference(s) between Undefined Behaviour, Unspecified Behaviour and Implementation Defined Behaviour.
You must also know that the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified.
For example:
int x = 5, y = 6;
int z = x++ + y++; //it is unspecified whether x++ or y++ will be evaluated first.
Another example here.
Now the Standard in §5/4 says
Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression.
What does it mean?
Informally it means that between two sequence points a variable must not be modified more than once.
In an expression statement, the next sequence point is usually at the terminating semicolon, and the previous sequence point is at the end of the previous statement. An expression may also contain intermediate sequence points.
From the above sentence the following expressions invoke Undefined Behaviour:
i++ * ++i; // UB, i is modified more than once btw two SPs
i = ++i; // UB, same as above
++i = 2; // UB, same as above
i = ++i + 1; // UB, same as above
++++++i; // UB, parsed as (++(++(++i)))
i = (i, ++i, ++i); // UB, there's no SP between `++i` (right most) and assignment to `i` (`i` is modified more than once btw two SPs)
But the following expressions are fine:
i = (i, ++i, 1) + 1; // well defined (AFAIK)
i = (++i, i++, i); // well defined
int j = i;
j = (++i, i++, j*i); // well defined
Furthermore, the prior value shall be accessed only to determine the value to be stored.
What does it mean? It means if an object is written to within a full expression, any and all accesses to it within the same expression must be directly involved in the computation of the value to be written.
For example in i = i + 1 all the access of i (in L.H.S and in R.H.S) are directly involved in computation of the value to be written. So it is fine.
This rule effectively constrains legal expressions to those in which the accesses demonstrably precede the modification.
Example 1:
std::printf("%d %d", i,++i); // invokes Undefined Behaviour because of Rule no 2
Example 2:
a[i] = i++ // or a[++i] = i or a[i++] = ++i etc
is disallowed because one of the accesses of i (the one in a[i]) has nothing to do with the value which ends up being stored in i (which happens over in i++), and so there's no good way to define--either for our understanding or the compiler's--whether the access should take place before or after the incremented value is stored. So the behaviour is undefined.
Example 3 :
int x = i + i++ ;// Similar to above
Follow up answer for C++11 here.
This is a follow up to my previous answer and contains C++11 related material..
Pre-requisites : An elementary knowledge of Relations (Mathematics).
Is it true that there are no Sequence Points in C++11?
Yes! This is very true.
Sequence Points have been replaced by Sequenced Before and Sequenced After (and Unsequenced and Indeterminately Sequenced) relations in C++11.
What exactly is this 'Sequenced before' thing?
Sequenced Before(§1.9/13) is a relation which is:
Asymmetric
Transitive
between evaluations executed by a single thread and induces a strict partial order1
Formally it means given any two evaluations(See below) A and B, if A is sequenced before B, then the execution of A shall precede the execution of B. If A is not sequenced before B and B is not sequenced before A, then A and B are unsequenced 2.
Evaluations A and B are indeterminately sequenced when either A is sequenced before B or B is sequenced before A, but it is unspecified which3.
[NOTES]
1 : A strict partial order is a binary relation "<" over a set P which is asymmetric, and transitive, i.e., for all a, b, and c in P, we have that:
........(i). if a < b then ¬ (b < a) (asymmetry);
........(ii). if a < b and b < c then a < c (transitivity).
2 : The execution of unsequenced evaluations can overlap.
3 : Indeterminately sequenced evaluations cannot overlap, but either could be executed first.
What is the meaning of the word 'evaluation' in context of C++11?
In C++11, evaluation of an expression (or a sub-expression) in general includes:
value computations (including determining the identity of an object for glvalue evaluation and fetching a value previously assigned to an object for prvalue evaluation) and
initiation of side effects.
Now (§1.9/14) says:
Every value computation and side effect associated with a full-expression is sequenced before every value computation and side effect associated with the next full-expression to be evaluated.
Trivial example:
int x;
x = 10;
++x;
Value computation and side effect associated with ++x is sequenced after the value computation and side effect of x = 10;
So there must be some relation between Undefined Behaviour and the above-mentioned things, right?
Yes! Right.
In (§1.9/15) it has been mentioned that
Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced4.
For example :
int main()
{
int num = 19 ;
num = (num << 3) + (num >> 3);
}
Evaluation of operands of + operator are unsequenced relative to each other.
Evaluation of operands of << and >> operators are unsequenced relative to each other.
4: In an expression that is evaluated more than once during the execution
of a program, unsequenced and indeterminately sequenced evaluations of its subexpressions need not be performed consistently in different evaluations.
(§1.9/15)
The value computations of the operands of an
operator are sequenced before the value computation of the result of the operator.
That means in x + y the value computation of x and y are sequenced before the value computation of (x + y).
More importantly
(§1.9/15) If a side effect on a scalar object is unsequenced relative to either
(a) another side effect on the same scalar object
or
(b) a value computation using the value of the same scalar object.
the behaviour is undefined.
Examples:
int i = 5, v[10] = { };
void f(int, int);
i = i++ * ++i; // Undefined Behaviour
i = ++i + i++; // Undefined Behaviour
i = ++i + ++i; // Undefined Behaviour
i = v[i++]; // Undefined Behaviour
i = v[++i]: // Well-defined Behavior
i = i++ + 1; // Undefined Behaviour
i = ++i + 1; // Well-defined Behaviour
++++i; // Well-defined Behaviour
f(i = -1, i = -1); // Undefined Behaviour (see below)
When calling a function (whether or not the function is inline), every value computation and side effect associated with any argument expression, or with the postfix expression designating the called function, is sequenced before execution of every expression or statement in the body of the called function. [Note: Value computations and side effects associated with different argument expressions are unsequenced. — end note]
Expressions (5), (7) and (8) do not invoke undefined behaviour. Check out the following answers for a more detailed explanation.
Multiple preincrement operations on a variable in C++0x
Unsequenced Value Computations
Final Note :
If you find any flaw in the post please leave a comment. Power-users (With rep >20000) please do not hesitate to edit the post for correcting typos and other mistakes.
C++17 (N4659) includes a proposal Refining Expression Evaluation Order for Idiomatic C++
which defines a stricter order of expression evaluation.
In particular, the following sentence
8.18 Assignment and compound assignment operators:....
In all cases, the assignment is sequenced after the value
computation of the right and left operands, and before the value computation of the assignment expression.
The right operand is sequenced before the left operand.
together with the following clarification
An expression X is said to be sequenced before an expression Y if every
value computation and every side effect associated with the expression X is sequenced before every value
computation and every side effect associated with the expression Y.
make several cases of previously undefined behavior valid, including the one in question:
a[++i] = i;
However several other similar cases still lead to undefined behavior.
In N4140:
i = i++ + 1; // the behavior is undefined
But in N4659
i = i++ + 1; // the value of i is incremented
i = i++ + i; // the behavior is undefined
Of course, using a C++17 compliant compiler does not necessarily mean that one should start writing such expressions.
I am guessing there is a fundamental reason for the change, it isn't merely cosmetic to make the old interpretation clearer: that reason is concurrency. Unspecified order of elaboration is merely selection of one of several possible serial orderings, this is quite different to before and after orderings, because if there is no specified ordering, concurrent evaluation is possible: not so with the old rules. For example in:
f (a,b)
previously either a then b, or, b then a. Now, a and b can be evaluated with instructions interleaved or even on different cores.
In C99(ISO/IEC 9899:TC3) which seems absent from this discussion thus far the following steteents are made regarding order of evaluaiton.
[...]the order of evaluation of subexpressions and the order in which
side effects take place are both unspecified. (Section 6.5 pp 67)
The order of evaluation of the operands is unspecified. If an attempt
is made to modify the result of an assignment operator or to access it
after the next sequence point, the behavior[sic] is undefined.(Section
6.5.16 pp 91)

What does the ++ (or --) operator return? [duplicate]

This question already has answers here:
Why can't I do ++i++ in C-like languages?
(8 answers)
Closed 8 years ago.
While playing around with the ++ operator, I tried to write the following:
++i++;
I expected this to compile at first, but I got a compiler error:
The operand of an increment or decrement operator must be a variable,
property or indexer.
I then tried writing ++(i++) to help the compiler understand what I meant but it also (unsurprisingly) didn't work.
So I am left wondering what does the ++ operator return ? With the compiler error I am getting I was expecting ++i to not return an int representing the value of i incremented, but that is also not the case since I can do i = (++i) + 1 with success...
Anybody have any idea why the ++ operator cannot be chained ?
Also, (++i).GetType() does return System.Int32.
In C# The ++ operator returns the value before (for i++) or after (for ++i) incrementing.
The error you're seeing is because that operator can ONLY be used on a variable, property, or indexer. The reason is because the intent of the operator is to increment the variable that is being referenced. You can't use it on an expression or other type. What would (9++) do?
You expect (i++)++ to be equivalent to i++; i++. But i++ returns a value and internally increments i. Since you can't apply the ++ operator to a value chaining is not possible.
The difference in C++ is that the ++ prefix operator takes a reference as an input, and returns a reference to the original value, so you can chain the operator since it's just using the pointer instead of a value. The postfix operator returns a value and thus cannot be chained.
The result of the ++ or -- operator is the value of the variable, property, or indexer, and not the variable, property, or indexer itself.
You can't double-increment a variable like (i++)++ for the same reason you can't increment a value by itself like 100++.
If I can borrow terminology from C or C++, the ++ operator here returns an "r-value". An r-value doesn't map to a language type, it's a syntactical trick to distinguish what's assignable (modifiable) and what isn't.
Something that you can find on the left side of an assignment operation is called an l-value (left value), and things that you can find on the right side of an assignment are "r-values" (right values). The ++ operator has to operate on an l-value, because it needs to assign to it. However, the returned expression has to be an r-value, because it wouldn't make sense to do i++ = 4 in C#, just like it wouldn't make sense to do foo.Bar() = 4 or 1 = 5.
C# doesn't have lvalues or rvalues per se, but it limits what can be found on the left side of an assignment to variables, properties and indexer operations. This is, not coincidentally, also what you can use the ++ operator on.
I realized that you cannot use ++ before or after an expression.
When you use:
++(i++);
you are doing something like:
++(<expression>)
The compiler resolve the expression first and then it will increment the result of the expression and that sound crazy. The operand ++ works by increment an immediate variable no the result of an expression.
How the programming expressions are evaluated? The grammar of the Language (BNF) http://people.cis.ksu.edu/~schmidt/301s11/Lectures/bnfT.html
Here another example of the correct use of this operand ++
int i = 0, j = 0;
int sum = i++ + j++;
//result sum = 0, i = 1, j = 1
This operand ++ is messy, since do 3 thing at once (read, increment, assignment). I personally don't uses in large expressions, such as the example above: i++ + j++. But I still use it in the for-loop or while-loop by itself.
Even a short expression such as i = j++; is a mess. Keep your code simple and easy to understand. The same expression can be write like:
i = j;
j++; //or j+=1;

Why do both ++i and i++ generate temporaries

I recall reading somewhere that for a variable int i both ++i and i++ generate a temporary in C#. Does anyone know why that is the case? Is their performance identical?
UPDATE
So from Eric Lippert's answer in the duplicate, the steps for pre-increment are as follows:
For pre-increment
1) x is evaluated to produce the variable
2) the value of the variable is copied to a temporary location
3) the temporary value is incremented to produce a new value (not overwriting the temporary!)
4) the new value is stored in the variable
5) the result of the operation is the new value
Why is step 2 necessary? Why not increment the variable in place?
The answer is: they don't. Not in the sense implied by the title.
First please note: as per Eric's article (which, surprisingly, was criticised by many), the sequence of events that takes place in pre-increment and post-increment in C# is identical. Not just similar, but identical. The same things happen in the same order.
Second, there are no 'temporaries' as such. the 'temporary location' Eric is referring to is conceptual, but corresponds in practice to a machine register. A value is copied from memory to a register, the value is incremented, and the value is stored back into memory.
But there is another aspect. Unlike C/C++, C# guarantees the order of evaluation of expressions. In C# the following code is well-defined, where in C it is not.
j = ++i + i++;
But take something simpler:
j = ++i + f(i); // first
j = i++ + f(i); // second
In the first case the value of the variable is available for use in the subsequent expression, but in the second case it is not. Instead there is a conceptual temporary resulting from the first increment that is used in the following function call. An additional register may be used in the second case.

What is the difference between i++ and ++i?

I've seen them both being used in numerous pieces of C# code, and I'd like to know when to use i++ and when to use ++i?
(i being a number variable like int, float, double, etc).
The typical answer to this question, unfortunately posted here already, is that one does the increment "before" remaining operations and the other does the increment "after" remaining operations. Though that intuitively gets the idea across, that statement is on the face of it completely wrong. The sequence of events in time is extremely well-defined in C#, and it is emphatically not the case that the prefix (++var) and postfix (var++) versions of ++ do things in a different order with respect to other operations.
It is unsurprising that you'll see a lot of wrong answers to this question. A great many "teach yourself C#" books also get it wrong. Also, the way C# does it is different than how C does it. Many people reason as though C# and C are the same language; they are not. The design of the increment and decrement operators in C# in my opinion avoids the design flaws of these operators in C.
There are two questions that must be answered to determine what exactly the operation of prefix and postfix ++ are in C#. The first question is what is the result? and the second question is when does the side effect of the increment take place?
It is not obvious what the answer to either question is, but it is actually quite simple once you see it. Let me spell out for you precisely what x++ and ++x do for a variable x.
For the prefix form (++x):
x is evaluated to produce the variable
The value of the variable is copied to a temporary location
The temporary value is incremented to produce a new value (not overwriting the temporary!)
The new value is stored in the variable
The result of the operation is the new value (i.e. the incremented value of the temporary)
For the postfix form (x++):
x is evaluated to produce the variable
The value of the variable is copied to a temporary location
The temporary value is incremented to produce a new value (not overwriting the temporary!)
The new value is stored in the variable
The result of the operation is the value of the temporary
Some things to notice:
First, the order of events in time is exactly the same in both cases. Again, it is absolutely not the case that the order of events in time changes between prefix and postfix. It is entirely false to say that the evaluation happens before other evaluations or after other evaluations. The evaluations happen in exactly the same order in both cases as you can see by steps 1 through 4 being identical. The only difference is the last step - whether the result is the value of the temporary, or the new, incremented value.
You can easily demonstrate this with a simple C# console app:
public class Application
{
public static int currentValue = 0;
public static void Main()
{
Console.WriteLine("Test 1: ++x");
(++currentValue).TestMethod();
Console.WriteLine("\nTest 2: x++");
(currentValue++).TestMethod();
Console.WriteLine("\nTest 3: ++x");
(++currentValue).TestMethod();
Console.ReadKey();
}
}
public static class ExtensionMethods
{
public static void TestMethod(this int passedInValue)
{
Console.WriteLine($"Current:{Application.currentValue} Passed-in:{passedInValue}");
}
}
Here are the results...
Test 1: ++x
Current:1 Passed-in:1
Test 2: x++
Current:2 Passed-in:1
Test 3: ++x
Current:3 Passed-in:3
In the first test, you can see that both currentValue and what was passed into the TestMethod() extension show the same value, as expected.
However, in the second case, people will try to tell you that the increment of currentValue happens after the call to TestMethod(), but as you can see from the results, it happens before the call as indicated by the 'Current:2' result.
In this case, first the value of currentValue is stored in a temporary. Next, an incremented version of that value is stored back in currentValue but without touching the temporary which still stores the original value. Finally that temporary is passed to TestMethod(). If the increment happened after the call to TestMethod() then it would write out the same, non-incremented value twice, but it does not.
It's important to note that the value returned from both the currentValue++ and ++currentValue operations are based on the temporary and not the actual value stored in the variable at the time either operation exits.
Recall in the order of operations above, the first two steps copy the then-current value of the variable into the temporary. That is what's used to calculate the return value; in the case of the prefix version, it's that temporary value incremented while in the case of the suffix version, it's that value directly/non-incremented. The variable itself is not read again after the initial storage into the temporary.
Put more simply, the postfix version returns the value that was read from the variable (i.e. the value of the temporary) while the prefix version returns the value that was written back to the variable (i.e. the incremented value of the temporary). Neither return the variable's value.
This is important to understand because the variable itself could be volatile and have changed on another thread which means the return value of those operations could differ from the current value stored in the variable.
It is surprisingly common for people to get very confused about precedence, associativity, and the order in which side effects are executed, I suspect mostly because it is so confusing in C. C# has been carefully designed to be less confusing in all these regards. For some additional analysis of these issues, including me further demonstrating the falsity of the idea that prefix and postfix operations "move stuff around in time" see:
https://ericlippert.com/2009/08/10/precedence-vs-order-redux/
which led to this SO question:
int[] arr={0}; int value = arr[arr[0]++]; Value = 1?
You might also be interested in my previous articles on the subject:
https://ericlippert.com/2008/05/23/precedence-vs-associativity-vs-order/
and
https://ericlippert.com/2007/08/14/c-and-the-pit-of-despair/
and an interesting case where C makes it hard to reason about correctness:
https://learn.microsoft.com/archive/blogs/ericlippert/bad-recursion-revisited
Also, we run into similar subtle issues when considering other operations that have side effects, such as chained simple assignments:
https://learn.microsoft.com/archive/blogs/ericlippert/chaining-simple-assignments-is-not-so-simple
And here's an interesting post on why the increment operators result in values in C# rather than in variables:
Why can't I do ++i++ in C-like languages?
Oddly it looks like the other two answers don't spell it out, and it's definitely worth saying:
i++ means 'tell me the value of i, then increment'
++i means 'increment i, then tell me the value'
They are Pre-increment, post-increment operators. In both cases the variable is incremented, but if you were to take the value of both expressions in exactly the same cases, the result will differ.
If you have:
int i = 10;
int x = ++i;
then x will be 11.
But if you have:
int i = 10;
int x = i++;
then x will be 10.
Note as Eric points out, the increment occurs at the same time in both cases, but it's what value is given as the result that differs (thanks Eric!).
Generally, I like to use ++i unless there's a good reason not to. For example, when writing a loop, I like to use:
for (int i = 0; i < 10; ++i) {
}
Or, if I just need to increment a variable, I like to use:
++x;
Normally, one way or the other doesn't have much significance and comes down to coding style, but if you are using the operators inside other assignments (like in my original examples), it's important to be aware of potential side effects.
int i = 0;
Console.WriteLine(i++); // Prints 0. Then value of "i" becomes 1.
Console.WriteLine(--i); // Value of "i" becomes 0. Then prints 0.
Does this answer your question ?
The way the operator works is that it gets incremented at the same time, but if it is before a variable, the expression will evaluate with the incremented/decremented variable:
int x = 0; //x is 0
int y = ++x; //x is 1 and y is 1
If it is after the variable the current statement will get executed with the original variable, as if it had not yet been incremented/decremented:
int x = 0; //x is 0
int y = x++; //'y = x' is evaluated with x=0, but x is still incremented. So, x is 1, but y is 0
I agree with dcp in using pre-increment/decrement (++x) unless necessary. Really the only time I use the post-increment/decrement is in while loops or loops of that sort. These loops are the same:
while (x < 5) //evaluates conditional statement
{
//some code
++x; //increments x
}
or
while (x++ < 5) //evaluates conditional statement with x value before increment, and x is incremented
{
//some code
}
You can also do this while indexing arrays and such:
int i = 0;
int[] MyArray = new int[2];
MyArray[i++] = 1234; //sets array at index 0 to '1234' and i is incremented
MyArray[i] = 5678; //sets array at index 1 to '5678'
int temp = MyArray[--i]; //temp is 1234 (becasue of pre-decrement);
Etc, etc...
Just for the record, in C++, if you can use either (i.e.) you don't care about the ordering of operations (you just want to increment or decrement and use it later) the prefix operator is more efficient since it doesn't have to create a temporary copy of the object. Unfortunately, most people use posfix (var++) instead of prefix (++var), just because that is what we learned initially. (I was asked about this in an interview). Not sure if this is true in C#, but I assume it would be.
I think I'll try answering the question using code. Imagine the following methods for, say, int:
// The following are equivalent:
// ++i;
// PlusPlusInt(ref i);
//
// The argument "value" is passed as a reference,
// meaning we're not incrementing a copy.
static int PlusPlusInt(ref int value)
{
// Increment the value.
value = value + 1;
// Return the incremented value.
return value;
}
// The following are equivalent:
// i++;
// IntPlusPlus(ref i);
//
// The argument "value" is passed as a reference,
// meaning we're not incrementing a copy.
static int IntPlusPlus(ref int value)
{
// Keep the original value around before incrementing it.
int temp = value;
// Increment the value.
value = value + 1;
// Return what the value WAS.
return temp;
}
Assuming you know how ref works, this should clear this up really nicely. Explaining it in english is a lot more clunky in my opinion.

Categories