Today I came a cross an article by Eric Lippert where he was trying to clear the myth between the operators precedence and the order of evaluation. At the end there were two code snippets that got me confused, here is the first snippet:
int[] arr = {0};
int value = arr[arr[0]++];
Now when I think about the value of the variable value, I simply calculate it to be one. Here's how I thought it's working.
First declare arr as an array of int
with one item inside of it; this
item's value is 0.
Second get the value of arr[0] --0 in
this case.
Third get the value of arr[the value
of step 2] (which is still 0) --gets
arr[0] again --still 0.
Fourth assign the value of step 3
(0) to the variable value. --value =
0 now
Add to the value of step 2 1 --Now
arr[0] = 1.
Apparently this is wrong. I tried to search the c# specs for some explicit statement about when the increment is actually happening, but didn't find any.
The second snippet is from a comment of Eric's blog post on the topic:
int[] data = { 11, 22, 33 };
int i = 1;
data[i++] = data[i] + 5;
Now here's how I think this program will execute --after declaring the array and assigning 1 to i. [plz bear with me]
Get data[i] --1
Add to the value of step 1 the value
5 --6
Assign to data[i] (which is still 1)
the value of step 2 --data[i] = 6
Increment i -- i = 2
According to my understanding, this array now should contain the values {11, 27, 33}. However, when I looped to print the array values I got: {11, 38, 33}. This means that the post increment happened before dereferencing the array!
How come? Isn't this post increment supposed to be post? i.e. happen after everything else. What am I missing guys?
The postincrement operation occurs as part of evaluating the overall expression. It's a side effect which occurs after the value is evaluated but before any other expressions are evaluated.
In other words, for any expression E, E++ (if legal) represents something like (pseudo-code):
T tmp = E;
E += 1;
return tmp;
That's all part of evaluating E++, before anything else is evaluated.
See section 7.5.9 of the C# 3.0 spec for more details.
Additionally, for assignment operations where the LHS is classified as a variable (as in this case), the LHS is evaluated before the RHS is evaluated.
So in your example:
int[] data = { 11, 22, 33 };
int i = 1;
data[i++] = data[i] + 5;
is equivalent to:
int[] data = { 11, 22, 33 };
int i = 1;
// Work out what the LHS is going to mean...
int index = i;
i++;
// We're going to assign to data[index], i.e. data[1]. Now i=2.
// Now evaluate the RHS
int rhs = data[i] + 5; // rhs = data[2] + 5 == 38
// Now assign:
data[index] = rhs;
The relevant bit of the specification for this is section 7.16.1 (C# 3.0 spec).
For the first snippet, the sequence is:
Declare arr as you described:
Retrieve the value of arr[0], which is 0
Increment the value of arr[0] to 1.
Retrieve the value of arr[(result of #2)] which is arr[0], which (per #3) is 1.
Store that result in value.
value = 1
For the second snippet, the evaluation is still left-to-right.
Where are we storing the result? In data[i++], which is data[1], but now i = 2
What are we adding? data[i] + 5, which is now data[2] + 5, which is 38.
The missing piece is that "post" doesn't mean "after EVERYTHING else." It just means "immediately after I retrieve the current value of that variable." A post increment happening "in the middle of" a line of code is completely normal.
data[i++] // => data[1], then i is incremented to 2
data[1] = data[2] + 5 // => 33 + 5
I would expect the post-increment operator to increment the variable after its value is used.
In this case, the variable is incremented before the second reference to the variable.
If it would not be so, you could write
data[i++] = data[i++] + data[i++] + data[i++] + 5
If it would be like you say, then you could remove the increment operator because it doesn't do actually anything, in the instruction I reported.
You have to think of assignments in three steps:
Evaluate left hand side (=get address where the value should be stored)
Evaluate right hand side
Assign the value from step 2 to the memory location from step 1.
If you have something like
A().B = C()
Then A() will run first, then C() will run, and then the property setter B will run.
Essentially, you have to think of your statement as
StoreInArray(data, i++, data[i] + 5);
The cause might be that some compilers optimize i++ to be ++i. Most of the time, the end result is the same, but it seems to me to be one of those rare occasions when the compiler is wrong.
I have no access to Visual Studio right now to confirm this, but try disabling code optimization and see if the results will stay the same.
Related
Could you please help me understand why variable a is not incremented in the first case but it is in the second case?
Case 1:
int a = 10;
a = a++;
Console.WriteLine(a); //prints 10
Case 2:
int a = 10;
int c = a++;
Console.WriteLine(a); //prints 11
I've gone through other similar questions but couldn't find any specifics.
UPDATE 1: How I think the program flows
Case 1:
1. 'a' is assigned 10
2. 'a' is assigned 10 before increment happens
3. 'a' is incremented by 1 (Why doesn't this step affect the final value of 'a'?)
4. 'a' is printed --> 10
Case 2:
1. 'a' is assigned 10
2. 'c' is assigned 10 before 'a' is incremented
3. 'a' is incremented by 1 (Why does the increment of 'a' work here?)
4. 'a' is printed --> 11
UPDATE 2: Thanks to all the answers, i think i've understood it, please correct me if i'm wrong.
Case 1:
1. `a` is assigned 10
2. Compiler evaluates `a++`, stores old value 10 and new value 11 as well. Since it's a post increment operation, assigns the old value to `a`. What i thought was, compiler would assign the old value 10 first and evaluate the `++` operation later. This is where i was wrong, compiler evaluates the RHS beforehand and assigns the value based on the operator.
4. 'a' is printed --> 10
Case 2:
1. `a` is assigned 10
2. Compiler evaluates `a++`, stores old value 10 and new value 11 as well. Since it's a post increment operation, assigns the old value to `c` but value of `a` is preserved with `11`.
4. 'a' is printed --> 11
For me the best way to understand some behaviour is to check IL generated. In your first case it's
IL_0001: ldc.i4.s 0A // stack: 10
IL_0003: stloc.0 // a = 10, stack: empty
IL_0004: ldloc.0 // stack: 10
IL_0005: dup // stack: 10, 10
IL_0006: ldc.i4.1 // stack: 10, 10, 1
IL_0007: add // stack: 10, 11
IL_0008: stloc.0 // a = 11, stack: 10
IL_0009: stloc.0 // a = 10, stack: empty
IL_000A: ldloc.0 // stack: 10
IL_000B: call System.Console.WriteLine
You can see that there's still that original value hanging on the stack and so the created 11 gets overwritten in the end.
Let me try to explain it in plain words.
When you are assigning a value to a variable (a = a++) the whole right side of the assignment gets evaluated first in order to guarantee the correct value, that's how it is. So nothing like you get 10, application goes on and increments value when you execute the next line.
Now, imagine post-increment as someone, who first increments a value, but gave you his world that you will get back the original value from the expression. And now you should see why the 11 is overwritten. Increment goes first and in the end, you get the promise original value (as IL proves).
The first case a = a++ is post-increment. Which says add 1 to a but return the previous value of a and then store the previous result back into a. This is basically a no-op.
If it was pre-increment, a = ++a, then a would be 11.
There is nothing undefined behavior here as someone describes in comment.
This is clearly defined behavior. To understand what is happening, you must first understand how the pre increment and post increment operator works.
Case1:
a++(post increment) will increment the value of a and stores it in a then returns the value before it was incremented.
So after executing a++;, value of a will be 11 but the operator will return 10.
Then a = a++; the assignment part becomes a = 10;.
Case2:
Sameway a++; will increment the value of a to 11 and returns the previous value (10). which will be assigned to c. c will be 10 but a will be 11 because you're not overwriting the value of a in this case.
Your Case1 is equal to:
int a = 10;
int temp = a;//10
a = a + 1; //11
a = temp; //10
Console.WriteLine(a);//10
and Case2 is equal to:
int a = 10;
int temp = a;//10
a = a + 1; //11
int c = temp;//10
Console.WriteLine(a);//11
I hope now that should be clear why you see what you see.
This is not undefined behavior nor is it a bug. From the MSDN Documentation:
The increment operator (++) increments its operand by 1.
The increment operator can appear before or after its operand.
The first form is a prefix increment operation. The result of the operation is the value of the operand after it has been incremented.
The second form is a postfix increment operation. The result of the operation is the value of the operand before it has been incremented.
So literally, MSDN tells you that if you use this syntax (postfix):
a = a++;
Then the result of the operation will assign a to a then increment. However, since the assignment operation already took place, you are losing the result of the increment.
Using it like this (prefix):
a = ++a;
This will increment a first, then assign the incremented value to a.
EDIT
I will try to break this down so hopefully you understand better.
First of all, know that ++ always returns a value. If you use the prefix version (e.g. ++a), it returns the value of a+1. If you use the postfix version (e.g. a++), it returns the value of a, before the increment occurs.
When you execute this code:
int a = 10;
a = a++;
You are telling the compiler to assign a the value of a before the increment. Therefore a equals 10 after this executes. The incremented value of 11 gets lost in the "nether". Note that you are not assigning 11 to a. You are assigning the old value, before the increment, which is why you are getting an output of 10.
When you execute this code:
int a = 10;
int b = a++;
After the last line executes, it is incrementing a to equal 11 and assigning 10 to 'b'. Since you are assigning to a different variable, then a is not getting overwritten by its original value of 10 as in the first example.
To make this even more visual, look here:
a = a++;
^ a is increased to 11, but the postfix increment returns the old value (10)
This line effectively becomes:
a = 10;
int b = a++;
^ a is increased to 11, but b gets assigned a's old value
This line effectively becomes:
int b = 10;
a = a + 1;
Does this clear it up?
I don't think that this is an undefined behavior , since in the first case :
int a = 10;
a = a++;
Console.WriteLine(a); //prints 10
The value of a is the value before the increment action , meaning that if we simplify a = a++ , then :
a = a ; // `a` has `10`
a++; // `a` has `11`
and only then a has the value 11 .
The 2nd case :
int a = 10;
int c = a++;
Console.WriteLine(a); //prints 11
Now c has the value 10 since the assignment operation makes the value on the left side to get the value of the variable (on the right side) before the increment action , and only then the value on the right side goes up by 1 .
To make it clear, there is a different between ++a, and a++.
Both two of them produces the same result, that is to increment a by 1, but the process is a little bit different and it is only seen by assigning it to another variable.
This is difference between pre and post increment that you might looking for
Case 1
int a,b;
a = 10;
b = a++; //Here b is assigned by a post-incremented a, therefore b value is still 10
Case 2
int a,b;
a = 10;
b = ++a; //Here b is assigned by a pre-incremented a, b value is now 11
Taken from http://en.wikipedia.org/wiki/Increment_and_decrement_operators
UPDATE
In reply to this problem
int a = 10;
a = a++;
the process is as followed:
1. variable 'a' with data type integer is created
2. variable 'a' value is assigned with 10
3. check the availability and the data type correctness of the right side. This means all operation on the right side (increment 'a') is being executed. 'a' is now 11
4. assign the post-incremented value to 'a', which is 10, 'a' is now 10
You should print out c in case 2.
The post incement operator result is always the value before increment. So first give the value 10 back then increment it to 11 and after that assign the operator result (10) to the left operand.
I have the following code
int a = 1, n = 1;
Convert.ToInt32(a = a++ + n--);
Console.WriteLine("a: " + a + " n : " + n);
//If you debug the second line of the code in quick watch the answer is 3.
The answer to above code should be 2, so it is. But if i debug it and see the value in quickwatch the value of a is printed 3. Any idea why the same code results two different values.
Also note that the increment/decrement operators tailing the variables will be executed after the variable is used in the calculation (but before the result is written into a).
This will be interpreted as a= 1 +1, not a = 2 + 0
Specifcally the programm flows:
Take 1 out of 'a' into calculation memory.
Increment 'a' by 1
take 1 out of 'n' into calculation memory
Decrement 'n' by 1
Set 'a' to the sum of the two values you extracted earlier (not the current values of those variables)
Often putting seperate steps into seperate lines can yield a lot better debugging. i.e.:
Hay I didn't know even If this question has asked before but my problem is as following.
In my c# console application I had declared a variable i with assigning a value as
int i = 0 and now I want increment i by 2, obviously I can use following cede.
int i = o;
i += 2;
Console.WriteLine(i);
Console.ReadLine();
//OUTPUT WILL BE 2
but this one is my alternate solution. As my lazy behavior I refuse to use this code and I had used following code.
int i = 0;
i += i++;
Console.WriteLine(i);
Console.ReadLine();
In above code I had accepted FIRST i++ will increment by one and than after it will again increment by i+=i but this thing is not happen.!!!
I doesn't know why this thing is happening may be I had done something wrong or some compilation problem.?????
Can any one suggest me why this happening????
I just want to know why code no 2 is not working? what is happening in there?
The i++ returns the value of i (0) and then adds 1. i++ is called post-increment.
What you are after is ++i, which will first increase by one and then return the increased number.
(see http://msdn.microsoft.com/en-us/library/aa691363(v=vs.71).aspx for details about increment operators)
i needs to start off with 1 to make this work.
int i = 1;
EDIT::
int i = 0;
i += i++;
Your code above expresses the following:
i + 0 then add one
if you use i += ++i; then you'll get i + 1 as it processed the increment beforehand.
What your code is doing:
"i++" is evaluated. The value of "i++" is the value of i before the increment happens.
As part of the evaluation of "i++", i is incremented by one. Now i has the value of 1;
The assignment is executed. i is assigned the value of "i++", which is the value of i before the increment - that is, 0.
That is, "i = i++" roughly translates to
int oldValue = i;
i = i + 1
//is the same thing as
i = oldValue;
The post-increment operator increments the value of your integer "i" after the execution of your i++
For your information:
i++ will increment the value of i, but return the pre-incremented value.
++i will increment the value of i, and then return the incremented value.
so the best way of doing the 2 step increment is like that:
i +=2
I was wondering if anyone could tell me about the i++ operator in C#.
I know it adds one to the int value, but I wouldn't have a clue where to use it, and if its only for loop statements, or can be used in general projects.
If I could get some practical examples of where you might use the i++ operator, thank you.
This is post-increment,which means that the increment will be done after the execution of the statement
int i=0;
Console.Write(i++); // still 0
Console.Write(i); // prints 1, it is incremented
In general, given this declaration:
var myNum = 0;
anywhere you would normally do this:
myNum += 1;
You could just do this:
myNum++;
What you are referring to is the C# post increment operator, common use case are :
Incrementing the counter variable in a standard for loop
Incrementing the counter variable in a while loop
Accessing an array in sequential order (3)
Example (3) :
int[] table = { 0, 1, 2, 3, 4, 5, 6 };
int i = 0;
int j = table[i++]; //Access the table array element 0
int k = table[i++]; //Access the table array element 1
int l = table[i++]; //Access the table array element 2
So, whats the post increment operator really does ?
It return the value of the variable and then increment it's value by 1 unit .
The expression i++ is just like x == y > 0 ? x : z which both are syntactic sugar.
x = i++ saves you the space of writing x=i; i=i+1;
Is it good or bad? There is really no exact answer to this.
I personally avoid these expressions as they make my code look complex, sometimes hard to debug. Always think code readability instead of write-ability, always think how your code looks readable instead of how easy is it to write it
I am a little confused why this is not working:
id = (isChar ? (id + 1 > 122 ? 65 : id++) : id++);
The input here can either be an int or a char converted to an INT. I am then incrementing the id and increasing either the int or char. The problem is, when I input a char, the number does not seem to change?
This is an extremely poor programming practice that you're using. Conditional expressions should not have side effects; they should compute values. You are executing the side effect and then throwing away the side effect! You should either (1) make a side-effect-free version:
id = (isChar && id > 121) ? 65 : id + 1;
or (2) write your side-effecting version as statements, not expressions:
if (isChar && id > 121)
id = 65;
else
id++;
Let's take a look in more detail what is wrong with this simplified version of your original buggy code:
id = whatever ? 65 : id++;
Suppose whatever is false. What happens? id++ is morally equivalent to:
int PostIncrement(ref int x)
{
int temp = x;
x = temp + 1;
return temp;
}
So suppose you did:
id = whatever ? 65 : PostIncrement(ref id);
What happens? Suppose id is 1. You pass it by reference to PostIncrement. PostIncrement makes a copy of the value of id -- 1 -- in temp. It then adds one to that -- 2 -- and assigns the result to id. So id is now 2. Then it returns 1.
Back in the caller, id is now 2, and then you assign the result of PostIncrement, which was 1, and now id is 1 again.
Do not use id++ to mean id + 1 because that is not at all what it means.
Change id++ to id + 1 in both cases. You are throwing away the change from the increment in the assignment, which is executed last.
As a general rule, avoid side-effects (such as ++) in complex expressions. They make the whole expression intractable. This has tripped you up here.
Better yet, increment id beforehand since you always seem to increment it:
id += 1;
if (isChar && id > 122)
id = 65;
or
id = (isChar && id > 121) ? 65 : id + 1;
The other answers are correct. You should consider their advice first, however, it is possible to fix this simply by moving the ++ operator before the variable, i.e. ++id.
Essentially, putting ++ after your variable (postfix increment operation) returns the value of the variable before the increment occurs. By moving the ++ ahead of your variable (prefix increment operation), it returns the value of the variable after the increment is performed. Note that in both cases the incremented value is still stored in the variable, only the value returned by the operation is affected.
See ++ Operator (C# Reference) for more details on that.