In C# the operands of + are evaulated in left-to-right order. In C and C++ the order of evaluation for the operands of + is unspecifed. For C# your examples work as follows: y = x + x++; ^ x is 1 ^ x is increased to 2, but the postfix increment returns the old value (1) y = 2 y = x++ + x; ^ x becomes 2, but postfix increment returns the old value (1) ^ x is now 2 here y = 3.
2 This doesn't really address his question though, in both examples he is using postfix. I don't have a C or C# environment handy, so I am curious what others have to say. – Matt Greer Oct 18 at 18:56 @MarkByers Thanks Mark, this is a very good visual of what is happening.
– timmy Oct 18 at 19:25 1 @Matt Greer Actually it does - x is 2 after "x++" returns, not after the whole statement. This is only defined in C# among the languages mentioned. In C/C++, it's undefined, and x could be zero, or infinity, or anything in between, or your computer could explode.
– Random832 Oct 18 at 21:26 1 Take careful note of Mark's phrasing. As Mark indicates, (in C#) x++ means "increment x, then return the old value of x. X++ does not mean, "return the value of x, then increment x.
– Brian Oct 19 at 16:41.
This question gets asks a fair amount. Be warned that every time someone asks this question a great many people post incorrect answers. Lots of people have incorrect ideas about how these operators work, including people who write programming books and thereby teach other people falsehoods.
Read the other answers here very carefully. For a correct analysis of the C# behaviour, see: C#: what is the difference between i++ and ++i? For C++ any behaviour is correct behaviour, in those cases where you are observing a side effect.
C++ does not define when the side effect of the increment is visible. Any two compilers can do it differently. A good rule to follow is to not rely on the order in which side effects happen in any language, but certainly do not rely on it in C++, because it is not reliable.To look at your specific case: int x, y; x = 1; y = x + x++; You report that x and y are both 2.
That is correct in C#. In C# the correct behaviour is: evaluate y as a variable evaluate x as a value -- it is 1 evaluate x++ as a value. This evaluates x as a variable, then takes its original value which is 1, then increments that value, which is 2, then assigns 2 to x and then results in the original value, which is 1.
Evaluate 1 + 1, which is 2 assign 2 to y. So x and y are both 2 in C#. C++ can do the same thing, but it is permitted to evaluate the addition in right-to-left order.
That is, it is permitted to do: evaluate x++ as a value. This evaluates x as a variable, then takes its original value which is 1, then increments that value, which is 2, then assigns 2 to x and then results in the original value, which is 1. Evaluate x as a value -- it is 2 evaluate 1 + 2, which is 3 evaluate y as a variable assign 3 to y.
C++ is also permitted to do this: evaluate x++ as a value. This evaluates x as a variable, then takes its original value which is 1, then increments that value, which is 2 ... step missing here ... and then results in the original value, which is 1. Evaluate x as a value -- it is 1 evaluate 1 + 1, which is 2 assigns 2 to x -- the step that was missing before.
Evaluate y as a variable assign 2 to y. So in C++, you can get y as 3 or 2, depending on the whim of the compiler writer.In C# you always get that y is 2. In C++, the increment's assignment can happen at any time, as long as it does happen.
In C#, the increment's assignment must happen after the incremented value is computed and before the original value is used.(When observed from the executing thread; if you are trying to observe this stuff from another thread or threads, all bets are off.) In your second example: y = x++ + x; In C# the required behaviour is: evaluate y as a variable evaluate x++ as a value. This evaluates x as a variable, then takes its original value which is 1, then increments that value, which is 2, then assigns 2 to x and then results in the original value, which is 1. Evaluate x as a value -- it is 2 evaluate 1 + 2, which is 3 assign 3 to y.So the correct answer in C# is that y is 3 and x is 2.
Again, C++ can do these steps in any order. C++ is permitted to do: evaluate x as a value -- it is 1 evaluate x++ as a value. This evaluates x as a variable, then takes its original value which is 1, then increments that value, which is 2, then assigns 2 to x and then results in the original value, which is 1.
Evaluate 1 + 1, which is 2 evaluate y as a variable assign 2 to y. Again, in C++ the correct answer is that y is 2 or 3, depending on the whim of the compiler writer.In C# the correct answer is that y is 3.
4 In summary: if you have x++ or ++x, then x better not be anywhere else on that line. – Mooing Duck Oct 18 at 19:03 thx for the tips :) – Shredder Oct 18 at 19:03 1 @MooingDuck: That is a good rule of thumb. The actual rule in C++ is to know what the rules are for "sequence points" and follow them.(Look it up on Wikipedia if you don't know what a "sequence point" is in C++.) – Eric Lippert Oct 18 at 19:12 1 @timmy: Good question!
The short answer is that the C# compiler generates a variety of different MSIL opcodes depending on the specific situation and whether or not optimizations are turned on. But IL does not actually run of course. The jitter turns those opcodes into machine-specific instructions.
How the jitter chooses to allocate temporary memory is up to it; odds are good that it enregisters the temp. For the exact details, either (1) write a bunch of C# programs that do different kinds of ++ and see what ILDASM and the debugger tell you, or (2) open up a new question. – Eric Lippert Oct 18 at 21:19 1 @timmy: and of course if the jitter can prove that doing so is safe, it need never allocate any temporary.
It could simply enregister the variable and update it to the correct value in place, if it knows that the value and the side effect are not observed. Obviously that is the common situation; if you have for(int I = 0; I – Eric Lippert Oct 18 at 21:22.
In both cases, the increment was applied after the x was used. In the first, it was evaluated as follows: y = 1 + 1 (incremented to 2) in the second y = 1 (incremented to 2) + 2. That's why you got different answers.
Good explanation – Shredder Oct 18 at 19:02.
In C and C++: The output is Unspecified. Reference - C++03 Standard: Section 5: Expressions, Para 4: except where noted e.g. Special rules for && and ||, 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.In C99 Section 6.5. "The grouping of operators and operands is indicated by the syntax.72) Except as specified later (for the function-call (), &&, ||,? :, and comma operators), the order of evaluation of subexpressions and the order in which side effects take place are both unspecified.
I though unspecified meant Implementation Defined. (I could be wrong) – Mooing Duck Oct 18 at 19:05 @MooingDuck: No it is not, Check undefined,unspecified and implementation defined behavior – Als Oct 18 at 19:07 No, no: the behavior is not unspecified, it is undefined. You forgot the rest of §5/4: "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.
Furthermore, the prior value shall be accessed only to determine the value to be stored. " The OP's code violates the second sentence. – James McNellis Nov 6 at 17:37.
X + x++ and x++ + x are an example of pathological side-effects cases you don't want to depend on. X++ and ++x both increment x, but in adding x the order of evaluation is undefined - the compiler can choose which 'side' it evaluates first.
It's not undefined. In both cases, you only modify x once and the order of operation is completely defined by the standard. – Luchian Grigore Oct 18 at 19:00 @n8wrl Not sure I agree with that.
Parenthesis always helps. – Lou Oct 18 at 19:00 Parenthesis do help, but that doesn't change the fact. – Luchian Grigore Oct 18 at 19:03 2 @LuchianGrigore: The order in which the operators execute is defined.
The order in which the operands are evaluated and side effects become visible is not defined in C++. In the cases given by the original poster, the behaviour is in fact unspecified by the C++ specification. – Eric Lippert Oct 18 at 19:17.
The expressions x++ and ++x have both a result (or value) and a side effect. If we restrict our discussion to integral type operands, the result of x++ is whatever the current value of x is. The side effect is to increment x by 1.
Thus, given the code x = 0; y = x++; the result will be x == 1 and y == 0 (assuming x and y are integral types). For ++x, the result is 1 plus the current value of x. The side effect is to increment x by 1.
Thus, given the code x = 0; y = ++x; the result will be x == y == 1. What distinguishes C and C++ from C# is when operands are evaluated and when the side effects are applied. C# guarantees that operands in an expression are always evaluated left-to-right.
C and C++ only guarantee left-to-right evaluation for the &&, ||,? :, comma, and function-call () operators - for all other operators, the order in which operands are evaluated is unspecified. Similarly, in C#, the side effects of x++ and ++x will be applied immediately after the expression has been evaluated, whereas C and C++ only require that the side effect be applied before the next sequence point.
C#'s rules on evaluation guarantee that the expressions like x = x++, a = b++ * b++, and ai = i++ are well-defined, whereas the C and C++ language definitions explicitly say such expressions result in undefined behavior (any result is possible).
Consider: y = x + x++; Whether its behavior is defined or not (it's undefined in C and C++; apparently it's well defined in C#), whatever it is you're trying to do, there's bound to be a better way to express it. If you're assuming strict left-to-right evaluation, then the above could be written as: y = x * 2; x ++; The meaning is clear and unambiguous to any reader who knows what =, *, and ++ mean, and future maintainers of your code won't be tempted to hunt you down. Or you could write x + x or x If you insist, you could even write: y = x++ * 2; That's a little terse for my personal tastes, but it's still unambiguous.
If you want to understand somebody else's code (which admittedly is something programmers spend a great deal of time doing), then understanding convoluted expressions can be important. But when you're writing your own code, clarity is more important than saving keystrokes (or showing off how well you know the operator precedence charts).
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.