This question already has answers here:
What is the difference between i++ and ++i in C#?
(7 answers)
Closed 9 years ago.
I am reading C# 5.0 in a nutshell and I have the following statements:
int x = 0;
while (true)
{
if (x++ > 5)
break ; // break from the loop
}
x.Dump();
Executing the statements on LINQPad 4 the output is 7.
I still don't understand WHY?. Why it is not 6 being the condition: x++>5
The ++ operator increments the value and returns the original value.
So when x was 5, x was incremented and the condition 5 > 5 is evaluated.
Then, when x was 6, x was incremented and the condition 6 > 5 is evaluated, which results in the break. Because x was still incremented, the value of x in the end is 7.
People often say that when the ++ operator is use as a postfix, the increment is executed after the comparison, but this is not technically true, which is shown by decompilation in LinqPad:
int x = 5;
if (x++ > 5)
Console.WriteLine(x);
IL:
IL_0001: ldc.i4.5
IL_0002: stloc.0 // x
IL_0003: ldloc.0 // x
IL_0004: dup
IL_0005: ldc.i4.1
IL_0006: add // <---- Increment
IL_0007: stloc.0 // x <-- Result of increment is popped from the stack and stored in a variable
IL_0008: ldc.i4.5
IL_0009: cgt // <---- Comparison
IL_000B: ldc.i4.0
IL_000C: ceq
IL_000E: stloc.1 // CS$4$0000
IL_000F: ldloc.1 // CS$4$0000
IL_0010: brtrue.s IL_0019
IL_0012: ldloc.0 // x
IL_0013: call System.Console.WriteLine
x++ > 5 means check the value of x against 5 then increment it. Which means your break is not reached until x == 7.
The result would be 6 if you used ++x, i.e. increment x and then test it against 5.
The following are the iterations of the loop:
x == 0 -> comparison returns false -> x increased to 1
x == 1 -> comparison returns false -> x increased to 2
x == 2 -> comparison returns false -> x increased to 3
x == 3 -> comparison returns false -> x increased to 4
x == 4 -> comparison returns false -> x increased to 5
x == 5 -> comparison returns false -> x increased to 6
x == 6 -> comparison returns true -> x increased to 7 -> if-block is entered and the loop is left
The last value of x, namely 7, will be output.
Note that the x++ operation modifies the value of x, after the comparison x > 5 is evaluated, but regardless of whether or not the comparison returns true and the if-block is entered.
On C#, the ++ unary operator, when wrote after its operand (it can be either ++x or x++) executes itself after evaluations in the expression. That means:
When x is 5, the expression is gonna be evaluated as false (5 is not > than 5) and then increment it to 6.
Then, when x is 6, the expression is gonna be evaluated as true yes (6 is > than 5), but then it is gonna increment again, breaking when x is 7.
The reason is that x++ will evaluate after the check. So when it finally gets to x == 6 the condition will be met (6 > 5) and then afterwards it will be incremented (to 7)
It is easier to explain with some alternate code, which will produce the same result:
while (true)
{
if(x > 5)
{
//x = 6
x++;
//x = 7
break;
}
x++;//x increments from 0 - 6, over 6 loops
}
You're evaluating x before you increment it, so your condition of 6 will cause the break and then it goes up 1 to 7. I think you're expecting this:
int x = 0;
while (true)
{
if (++x > 5)
break ; // break from the loop
}
x.Dump();
This will increment x before you evaluate its condition.
It is because of the ++
The ++ operator counts x one up everytime it hits the line.
And as you have a while(true) loop it will count x one up in the if statement everytime it reaches that if-statement.
x++ increments x after the value has been read. This means that when it increments once after the comparison fails.
++x on the other hand increments before the value is read.
Sure, it's 7 because even when it does the check for 6 > 5, it increments by one. Because of the unary operator x++.
Related
I can't figure out how I can remove right-hand zeros in a given binary number like this:
00110000 -> 11
1000 -> 1
According to my example, I know I can perform a right-shift of 4 and 3 to remove the unwanted zeros but I don't know how could I calculate the number of bits needed for the right-shift.
This should work:
if (x != 0)
{
while (x % 2 == 0)
x = x >> 1;
}
It basically says keep bit shifting right whilst the number is even (doesn't have 1 as the right-most bit).
As mentioned in the comments by #Streamline, the loop alone won't work for a value of 0, so you have to check it's not 0 first.
No need to check every time round the loop for this though because if x != 0 then x >> n will never be 0 given the other looping condition that we stop when x % 2 != 0
If you need to know the number of bit-shifts, you can add a counter to the loop.
If you don't want to change the value of x, you can assign it to a temporary variable and use that instead.
This question already has answers here:
How do Prefix (++x) and Postfix (x++) operations work?
(7 answers)
Closed 6 years ago.
While I am testing post increment operator in a simple console application, I realized that I did not understand full concept. It seems weird to me:
int i = 0;
bool b = i++ == i;
Console.WriteLine(b);
The output has been false. I have expected that it would be true. AFAIK, at line 2, because of the post increment, compiler does comparison and assigned b to true, after i incremented by one. But obviously I am wrong.
After that I modify the code like that:
int i = 0;
bool b = i == i++;
Console.WriteLine(b);
This time output has been true. What did change from first sample?
Suppose i has the value 0 initially, as it does in your examples.
i++ == i reads i (0), increments i, reads i again (1), and compares the two values: 0 == 1.
i == i++ reads i (0), reads i again (0), increments i, and compares the two values: 0 == 0.
The increment happens immediately after reading the old value.
Answering to your first snippet of code:
Here, bool b = i++ == i;is 0 == 1and this is because as you know i++ is a post increment so i remains 0 at i++ but after that part is finished executing and it is being compared to the right hand side which is i , by this time the value has change to 1 due to that previous post increment. This is why you are getting False when doing : bool b = i++ == i;.
Like #hvd said: The increment happens immediately after reading the old value.
The order of evaluation of the postfix and the equality operator is from left to right, so the code behaves as explained in the code comments.
int i = 0;
bool b = i++ == i;
// 1.) i++ returns old value i.e. 0
// 2.) but after that it increments and becomes 1
// 3.) hence, bool b = 0 == 1; --> evaluates to false
Console.WriteLine(b); // prints false
int i = 0;
bool b = i == i++;
// 1.) i returns old value i.e. 0
// 2.) i++ returns old value i.e. 0, as this is the end of the statement after that it would increment
// 3.) hence, bool b = 0 == 0; --> evaluates to true
Console.WriteLine(b); // prints true
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 this sample code
public class MyClass
{
private static int tempKey = 0;
public MyClass()
{
this.Key = --tempKey;
}
public int Key {get; set;}
}
What does --tempkey do exactly?
It decrements tempKey and returns new value. Compare with tempKey--, which also decrements tempKey, but returns the original value.
See Microsoft documentation here.
The increment operator (++) increments its operand by 1. The increment
operator can appear before or after its operand:
++ var
var ++
Where:
var An expression that denotes a storage location or a property or an
indexer.
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.
EDIT: This is valid for C#. Visual Basic doesn't have this increment/decrement operator.
In Visual Basic --tempKey is evaluated as -1 * (-1 * tempKey) which is equal to tempKey.
"--x" is pre-decrement arithmetic operator. Meaning the value is decremented by 1 before being used in the statement.
int x = 10;
Console.WriteLine(--x); // This will print 9
"x--" is post-decrement arithmetic operator. Meaning the value is used and then decremented by 1.
int x = 10;
Console.WriteLine(x--); // This will print 10
Console.WriteLine(x): // This will print 9
It decrements the variable by 1 and then evaluates to the decremented value. Therefore, in the example you gave, the constructor would decrement tempKey from 0 to -1 and then set Key to the same value of -1 as well. For instance:
int x = 5;
int y = --x; // x gets set to 4 and they y is also set to 4
int x2 = 5;
int y2 = x2--; // x2 gets set to 4 and then y gets set to 5 (x2's value prior to decrement)
There is no equivalent operator in VB. In VB, --tempKey would have no affect. A single minus sign before a variable name will negate the value. Two minus signs in a row before a variable name will negate the value twice, thereby returning it to the original value. For instance:
Dim x As Integer = 5
Dim y As Integer = --x ' x still equals 5 and y also gets assigned 5
In other words, it's the same as saying y = -1 * -1 * x.
It subtracts one from the value of tempkey.
More info can be found here: http://msdn.microsoft.com/en-us/library/6a71f45d.aspx
Specifically, from http://msdn.microsoft.com/en-us/library/wc3z3k8c.aspx
The decrement operator (--) decrements its operand by 1. The decrement
operator can appear before or after its operand: --variable and
variable--. The first form is a prefix decrement operation. The result
of the operation is the value of the operand "after" it has been
decremented. The second form is a postfix decrement operation. The
result of the operation is the value of the operand "before" it has
been decremented.
The -- operator is the subtraction operator. In this case, it subtracts one from the tempKey variable. Because it is before the variable, it subtracts the value first, before returning it into the this.Key value. If it was after the variable tempkey-- then it would subtract the value after returning the value into this.Key.
--i decrements the number and returns the decremented result, whereas i-- also decrements the number, but returns the pre-decremented result.
It is a pre-decrement operator. Effectively, it subtracts one from tempKey. Thus when the constructor MyClass is first called, tempKey changes its value to -1 and then this.Key gets the value -1. Since tempKey is static, each subsequent call for constructor will decrement tempKey.
I am a little confused about how the C# compiler handles pre- and post increments and decrements.
When I code the following:
int x = 4;
x = x++ + ++x;
x will have the value 10 afterwards. I think this is because the pre-increment sets x to 5, which makes it 5+5 which evaluates to 10. Then the post-increment will update x to 6, but this value will not be used because then 10 will be assigned to x.
But when I code:
int x = 4;
x = x-- - --x;
then x will be 2 afterwards. Can anyone explain why this is the case?
x-- will be 4, but will be 3 at the moment of --x, so it will end being 2, then you'll have
x = 4 - 2
btw, your first case will be x = 4 + 6
Here is a small example that will print out the values for each part, maybe this way you'll understand it better:
static void Main(string[] args)
{
int x = 4;
Console.WriteLine("x++: {0}", x++); //after this statement x = 5
Console.WriteLine("++x: {0}", ++x);
int y = 4;
Console.WriteLine("y--: {0}", y--); //after this statement y = 3
Console.WriteLine("--y: {0}", --y);
Console.ReadKey();
}
this prints out
x++: 4
++x: 6
y--: 4
--y: 2
Lets have a look at the IL that gets generated from that statement
IL_0002: ldloc.0
Loads the value of x onto the stack. Stack => (4)
IL_0003: dup
Duplicates the topmost item on the stack. Stack => (4, 4)
IL_0004: ldc.i4.1
Push 1 onto the stack. Stack => (1, 4, 4)
IL_0005: sub
Subtract the two top values and push result onto the stack. Stack => (3, 4)
IL_0006: stloc.0
Store the topmost value of the stack back to x. Stack => (4)
IL_0007: ldloc.0
Load the value of x back into the stack. Stack => (3, 4)
IL_0008: ldc.i4.1
Load the value 1 onto the stack. Stack => (1, 3, 4)
IL_0009: sub
Subtract the two. Stack => (2, 4)
IL_000A: dup
Duplicate the top value => (2, 2, 4)
IL_000B: stloc.0
Store the top value back to x. Stack => (2, 4)
IL_000C: sub
Subtract the two top values. Stack => (2)
IL_000D: stloc.0
Store this value back into x. x == 2
From your comment:
I thought that post- and pre-increments are executed after / before evaluation of the complete codeline - but they are executed after / before the evaluation of each item in the expression.
Your misunderstanding is an extremely common one. Note that in some languages, like C, it is not specified when the side effect becomes visible and it is therefore legal, but not required, for your statement to be true in C.
This is not the case in C#; in C# side effects of code on the left side of an expression are always observed to happen before code on the right side executes (from a single thread; in multithreaded scenarios all bets are off.)
For a more detailed explanation of what the increment operators do in C#, see:
What is the difference between i++ and ++i?
There are a great many additional links there to articles I've written on this often-misunderstood topic.
The most interesting thing that you'll get a completely different answer with C++.Net compiler.
int x = 4;
x = x++ + ++x; // x = 11
x = 4;
x = x-- - --x; // x = -1
Of course the difference in results is determined by different semantics - it seems normal. But despite the understanding the fact that two .net compilers don't behave in a similar manner for such basic things confuses me too.
In this example,
int x = 4;
x = x++ + ++x;
you can break it like:
x = 4++; which is = 5
x = 4 + ++5; which is 4 + 6
x = 10
Similarly,
int x = 4;
x = x-- - --x;
Here,
x = 4--; which is = 3
x = 4 - --3; which is 4 - 2
x = 2
Simply putting you can say, replace the current value of x, but for every ++ or -- add/subtract a value from x.
I think the explanation for the ++ + ++ case is wrong:
command...........value of x
..................undefined
int x=4 ..........4
x++...............5 (first summand is 4)
++x...............6 (second summand is 6)
x=summand1+summand2 ..4+6=10
Analogous the explanation for the -- - -- case is
command...........value of x
..................undefined
int x=4 ..........4
x--...............3 (subtactor is 4)
--x...............2 (subtrahend is 2)
x=subtractor-subtrahend ..4-2=10