postincrement operator interesting behaviour in Math.min() - java

I have a question,
In Java, does Math.min bind tighter than ++?
Let me illustrate with an example and maybe someone can explain to me why I get the results I get.
Here's a method I run:
private static void testIncrement() {
int x=10;
System.out.println(x++);
System.out.println(x);
x=10;
System.out.println("-----------");
System.out.println(++x);
System.out.println(x);
x=10;
System.out.println("-----------\n"+x); //10
x=Math.min(255, x++);
System.out.println(x); **//x=10 WHY NOT x=11?**
x=10;
System.out.println("-----------\n"+x);
x=Math.min(255, ++x);
System.out.println(x);
}
The results are:
10
11
-----------
11
11
-----------
10
10
-----------
10
11
On the line where I put //x=10 WHY NOT x=11?
I wonder why x is 10 and not 11. Maybe someone can explain this to me.
It looks as if Math.min create a copy of x (which is 10 at this time) which it uses to do Math.min. Then the original x is incremented from 10 to 11, but the copy which is still 10 comes out of Math.min and overwrites the incremented one.
Does this make sense?
Does anyone have an explanation for why x is 10 and not 11 in this case?
Thanks
PS - I totally understand How do the post increment (i++) and pre increment (++i) operators work in Java?

Let's deconstruct this line:
x = Math.min(255, x++);
The x++ means "remember the original value of x; then increment x; then the value of the expression is the original value". All of this happens before the assignment. So it's equivalent to:
int tmp = x; // x = 10, tmp = 10
x = x + 1; // x = 11, tmp = 10
x = Math.min(255, tmp); // x = 10
Hopefully that should make it clear. In particular, this has nothing to do with Math.min itself - it's just behaving as a normal method invocation. See section 15.14.2 of the JLS for more details.

Related

Left-to-right evaluation of expression versus operator precedence. why does left-to-right evaluation appear to win out?

Consider this code:
public class Incrdecr {
static int x = 3;
static int y = ++x * 5 / x-- + --x;
public static void main(String[] args){
System.out.println("x is " + x);
System.out.println("y is " + y);
}
It evaluates to the following:
x is 2
y is 7
This makes perfect sense, but let's take a quick look at the operator precedence table:
According to this, postfix operators are supposed to be evaluated first. Now, if we go back to our code, we will see that x-- should have been evaluated first, yet it wasn't. What am I not accounting for?
In other words, if we strictly follow the operator precedence table, then the expression would evaluate to:
y = ++x * 5 / 3 + --x;
which, of course, gives us an entirely different result for y.
You are correct in that your expression is evaluated left to right. This is the general evaluation order in Java (there are probably exceptions).
I think you have figured out what really happens:
x is incremented from 3 to 4 and its new value, 4, taken
5 is evaluated as 5
4 * 5 = 20
The value of x, 4, is taken for the division; the division yields 5 and x is decremented to 3.
x is further decremented to 2 before its value is taken for the final addition, which then yields 7.
Except: the compiler is allowed to swap steps only if it can guarantee that the result is the same. Therefore we know the result can only be 7.
Try to keep two concepts apart: evaluation order and operator precedence. They are not the same.
The precedence table tells you that the expression is understood as ((++x) * 5 / (x--)) + (--x) (that’s mostly good because ++(x * 5 / x)-- + --x would not make sense anyway).
To take a different example: f(x) - g(x) * h(x). The mehtods are called left to right: f(), then g() and h() last. The precedence table only tells you that the multiplication is done before the subtraction.
EDIT: Lew Bloch in a comment questioned that x would be evaluated to 4 at any point during calculation. To test this, I made the following variant of your program from the question:
public class Incrdecr {
static int x = 3;
static int y = p(++x) * 5 / p(x--) + p(--x);
private static int p(int i) {
System.out.println("p(): " + i);
return i;
}
public static void main(String[] args) {
System.out.println("x is " + x);
System.out.println("y is " + y);
}
}
This prints:
p(): 4
p(): 4
p(): 2
x is 2
y is 7
So yes, at two points x is evaluated to 4.
http://www.cs.bilkent.edu.tr/~guvenir/courses/CS101/op_precedence.html
Post increment/decrements follow left to right associativity of operators.
Pre increment/decrements follow right to left associativity of operators.
That is to say:
static int y = ++x * 5 / x-- + --x;
(x--) is stored as the current value of x (3) and then the rest is evaluated.
++x is evaluated to x=(x+1) forcing the evaluation of the post-increment because it is an assignment so it becomes (3) then --x is evaluated to x=(x-1) or 2.
This is functionally equivalent:
y = (x=x+1) * 5 / x-- + (x=x-1) (and it will run like this in your Java code)
The resulting equation is:
3 * 5 / 3 + 2.

eli5 can't understand this recursion process

public int recursive(int x){
if(x>10){
return x;
}
int y = x + 1;
int r = recursive(y);
System.out.println(y + " Y" + " R" + r + " X " + x);
return r;
}
public static void main(String[] args) {
System.out.println(new a().recursive(1));
}
This is a recursion I made to simplify a different method I could not understand but it has the same code line for line basically. I don't understand what is happening on this line int r = recursive(y);. I don't understand what the return r; even returns to or how it actively loops. When I system print R, it is always the same value each iteration which throws me off. If I change return r to return 555 the code still works but just returns 555 to the call from main.
output
11 Y R11 X 10
10 Y R11 X 9
9 Y R11 X 8
8 Y R11 X 7
7 Y R11 X 6
6 Y R11 X 5
5 Y R11 X 4
4 Y R11 X 3
3 Y R11 X 2
2 Y R11 X 1
11
Please eli5, I have viewed some recursion videos but they do not use a recursion thats laid out like this, with a return after a recursive call. int r = recursive(y);, how does r get its value here, and continue the loop, can't figure it out. It says set r equal to the return of recursive(y), but the return is r itself when the value for r has not been set or something?
Another issue I am having is how the system print is running as well, because I thought when the recursive part runs, it instantly restarts the method but it seems the entire method is running and looping
My friend it looks to me that your recursion breaking conditions is at r>10 so it always breaks at 11 thats the only cause............
suppose you have pass x=1
then your recursive(1) calls recursive(2), recursive(2) calls recursive(3), recursive(3) calls recursive(4) , recursive(4) calls recursive(5) , recursive(5) calls recursive(6), recursive(6) calls recursive(7), recursive(7) calls recursive(8), recursive(8) calls recursive(9), recursive(9) calls recursive(10), recursive(10) calls recursive(11)
and then recursion breaks and at recursive(11) it returns you 11 at this line `int r = recursive(y); so r becomes 11 and then recursion(10) returns you r and then recursion(9) returns you are and so on ................. for whole stack
You can think of it like a simple loop in this case, it just iterates untill x is > 10, so ret value of this recusrsion is 11, since it is the first number which is bigger than 10. Since nothing printed before recursive call you print the values in the reversed order, after x becomes 11, and function returns, previos stack frame contains values x == 10, y 10 + 1, and r contains return value of the functon => 11, same for previos frame and previos .....
When you enter 555, the first condition you have in your function is to return the value if it is greater than 10, so as 555 is greater than 10, it returns directly the value (555).
Now, for the recursion. It's pretty simple, just imagine how the code flows, you enter 1 as a parameter, is it greater than 10? No, so we move to the next line. We assign y the value of x plus 1, so X=1, and Y=2.
And then instead of returning a value, we call again the same function, but instead of 1 as a parameter, we call it with 2 as a parameter (the value of Y). And we start again (that's the point of recursion), but now X=2: Is 2 greater than 10? Now, so we move to the next line. We assign Y the value of the parameter (which is called X) plus 1, so now Y=3 and X=2. Remember that the variables' scope are only in the same function they are declared.
Repeat this, until the parameter goes above 10 (by adding one each time you call the recursive function), and then finally it returns a value! (in the condition where x > 10), so the function finishes and returns the value to the function who called it, which happens to assign that value to R and prints the result.
And so on, finishing each of the called functions that had different values as a parameter (1, 2, 3, etc until 10, as the function each time added one to the parameter and called itself).
I hope this helped you to understand it better, I'm not sure how to explain this simplier. I guess a 5 year old would have some problems to understand this :)

Behaviour of pre/post increment operators in Multiplication scenarios [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is there a difference between x++ and ++x in java?
Can anyone please explain me what is happening backyard to these statements?
int x=5;
System.out.println((x++)*x); //Gives output as 30
int x=5;
System.out.println((++x)*x); //Gives output as 36.
int x=5;
System.out.println((x++)*x); //Gives output as 30
You first take x (x = 5) as an operand. Then it's incremented to 6 which is second operand.
int x=5;
System.out.println((++x)*x); //Gives output as 36.
You first increment x by one (x = 6) and then multiply by x => 6 * 6 = 36
Multiplication is left-to-right associative, so the left operand will be evaluated first, then the right operand.
Post-increment operator will evaluate to current value of the variable, and increment it right after.
Pre-increment operator will increment the variable, then evaluate to the incremented value.
(x++) * x (x = 5)
--> 5 * x (increment deferred, x = 5)
--> 5 * x (increment x, x = 6)
--> 5 * 6
--> 30
(++x) * x (x = 5)
--> 6 * x (x is incremented before evaluated into expression, x = 6)
--> 6 * 6
--> 36
I mentioned the associativity here because it will affect the final result. If the associativity of multiplication is right-to-left instead of left-to-right, then the result will be 25 and 30 for post-increment and pre-increment expression respectively.
Assuming you understand that:
++x returns x+1 and increments x, while
x++ returns x and increments x,
the reason for the result is defined by the Java Language Specification #15.17
The multiplicative operators have the same precedence and are syntactically left-associative (they group left-to-right).
So in the first case, x++ is first evaluated, which returns 5 (it is the postfix operator) and adds 1 to x afterwards. Then the result of x++ (5) is multiplied by x (which is now 6) ==> 30
In the second case, ++x is first evaluated, which adds 1 to x and returns 6 (it is the prefix operator). Then the result of ++x (6) is multiplied by x (which is now 6) ==> 36
p++ means use then increment with a copy (copy is extremely local)
++p means increment and use without a copy
p++: use 5 and use incremented thing later in that line
++p: increment and use immediately
Post increment operators do the incrementation after the expression has been calculated.
In your first example, what is actually happening is:-
(x++) * x ; // (now incremented, 6 )
// x (5) * x+1 (6)
In your second example, the increment happens first
(++x) * x; // incremented straight away.
// x+1 (6) * x (now 6)

Why does this go into an infinite loop?

I have the following code:
public class Tests {
public static void main(String[] args) throws Exception {
int x = 0;
while(x<3) {
x = x++;
System.out.println(x);
}
}
}
We know he should have writen just x++ or x=x+1, but on x = x++ it should first attribute x to itself, and later increment it. Why does x continue with 0 as value?
--update
Here's the bytecode:
public class Tests extends java.lang.Object{
public Tests();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]) throws java.lang.Exception;
Code:
0: iconst_0
1: istore_1
2: iload_1
3: iconst_3
4: if_icmpge 22
7: iload_1
8: iinc 1, 1
11: istore_1
12: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
15: iload_1
16: invokevirtual #3; //Method java/io/PrintStream.println:(I)V
19: goto 2
22: return
}
I'll read about the instructions to try to understand...
Note: Originally I posted C# code in this answer for purposes of illustration, since C# allows you to pass int parameters by reference with the ref keyword. I've decided to update it with actual legal Java code using the first MutableInt class I found on Google to sort of approximate what ref does in C#. I can't really tell if that helps or hurts the answer. I will say that I personally haven't done all that much Java development; so for all I know there could be much more idiomatic ways to illustrate this point.
Perhaps if we write out a method to do the equivalent of what x++ does it will make this clearer.
public MutableInt postIncrement(MutableInt x) {
int valueBeforeIncrement = x.intValue();
x.add(1);
return new MutableInt(valueBeforeIncrement);
}
Right? Increment the value passed and return the original value: that's the definition of the postincrement operator.
Now, let's see how this behavior plays out in your example code:
MutableInt x = new MutableInt();
x = postIncrement(x);
postIncrement(x) does what? Increments x, yes. And then returns what x was before the increment. This return value then gets assigned to x.
So the order of values assigned to x is 0, then 1, then 0.
This might be clearer still if we re-write the above:
MutableInt x = new MutableInt(); // x is 0.
MutableInt temp = postIncrement(x); // Now x is 1, and temp is 0.
x = temp; // Now x is 0 again.
Your fixation on the fact that when you replace x on the left side of the above assignment with y, "you can see that it first increments x, and later attributes it to y" strikes me as confused. It is not x that is being assigned to y; it is the value formerly assigned to x. Really, injecting y makes things no different from the scenario above; we've simply got:
MutableInt x = new MutableInt(); // x is 0.
MutableInt y = new MutableInt(); // y is 0.
MutableInt temp = postIncrement(x); // Now x is 1, and temp is 0.
y = temp; // y is still 0.
So it's clear: x = x++ effectively does not change the value of x. It always causes x to have the values x0, then x0 + 1, and then x0 again.
Update: Incidentally, lest you doubt that x ever gets assigned to 1 "between" the increment operation and the assignment in the example above, I've thrown together a quick demo to illustrate that this intermediate value does indeed "exist," though it will never be "seen" on the executing thread.
The demo calls x = x++; in a loop while a separate thread continuously prints the value of x to the console.
public class Main {
public static volatile int x = 0;
public static void main(String[] args) {
LoopingThread t = new LoopingThread();
System.out.println("Starting background thread...");
t.start();
while (true) {
x = x++;
}
}
}
class LoopingThread extends Thread {
public #Override void run() {
while (true) {
System.out.println(Main.x);
}
}
}
Below is an excerpt of the above program's output. Notice the irregular occurrence of both 1s and 0s.
Starting background thread...
0
0
1
1
0
0
0
0
0
0
0
0
0
0
1
0
1
x = x++ works in the following way:
First it evaluates expression x++. Evaluation of this expression produces an expression value (which is the value of x before increment) and increments x.
Later it assigns the expression value to x, overwriting incremented value.
So, the sequence of events looks like follows (it's an actual decompiled bytecode, as produced by javap -c, with my comments):
8: iload_1 // Remember current value of x in the stack
9: iinc 1, 1 // Increment x (doesn't change the stack)
12: istore_1 // Write remebered value from the stack to x
For comparison, x = ++x:
8: iinc 1, 1 // Increment x
11: iload_1 // Push value of x onto stack
12: istore_1 // Pop value from the stack to x
This happens because the value of x doesn't get incremented at all.
x = x++;
is equivalent to
int temp = x;
x++;
x = temp;
Explanation:
Let's look at the byte code for this operation. Consider a sample class:
class test {
public static void main(String[] args) {
int i=0;
i=i++;
}
}
Now running the class disassembler on this we get:
$ javap -c test
Compiled from "test.java"
class test extends java.lang.Object{
test();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_0
1: istore_1
2: iload_1
3: iinc 1, 1
6: istore_1
7: return
}
Now the Java VM is stack based which means for each operation, the data will be pushed onto the stack and from the stack, the data will pop out to perform the operation. There is also another data structure, typically an array to store the local variables. The local variables are given ids which are just the indexes to the array.
Let us look at the mnemonics in main() method:
iconst_0: The constant value 0
is pushed on to the stack.
istore_1: The top element of the
stack is popped out and stored in the
local variable with index 1 which
is x.
iload_1 : The value at the
location 1 that is the value of x
which is 0, is pushed into the stack.
iinc 1, 1 : The value at the
memory location 1 is incremented by 1. So x now becomes
1.
istore_1 : The value at the top of
the stack is stored to the memory location1. That is 0 is assigned
to x overwriting its incremented value.
Hence the value of x does not change resulting in the infinite loop.
Prefix notation will increment the variable BEFORE the expression is evaluated.
Postfix notation will increment AFTER the expression evaluation.
However "=" has a lower operator precedence than "++".
So x=x++; should evaluate as follows
x prepared for assignment (evaluated)
x incremented
Previous value of x assigned to x.
None of the answers where quite spot on, so here goes:
When you're writing int x = x++, you're not assigning x to be itself at the new value, you're assigning x to be the return value of the x++ expression. Which happens to be the original value of x, as hinted in Colin Cochrane's answer .
For fun, test the following code:
public class Autoincrement {
public static void main(String[] args) {
int x = 0;
System.out.println(x++);
System.out.println(x);
}
}
The result will be
0
1
The return value of the expression is the initial value of x, which is zero. But later on, when reading the value of x, we receive the updated value , that is one.
It has been already explained well by other. I just include the links to the relevant Java specification sections.
x = x++ is an expression. Java will follow the evaluation order.
It will first evaluate the expression x++, which will increment x and set result value to the previous value of x.
Then it will assign the expression result to the variable x. At the end, x is back at its previous value.
This statement:
x = x++;
evaluates like this:
Push x onto the stack;
Increment x;
Pop x from the stack.
So the value is unchanged. Compare that to:
x = ++x;
which evaluates as:
Increment x;
Push x onto the stack;
Pop x from the stack.
What you want is:
while (x < 3) {
x++;
System.out.println(x);
}
The answer is pretty straightforward. It has to do with the order things are evaluated. x++ returns the value x then increments x.
Consequently, the value of the expression x++ is 0. So you are assigning x=0 each time in the loop. Certainly x++ increments this value, but that happens before the assignment.
From http://download.oracle.com/javase/tutorial/java/nutsandbolts/op1.html
The increment/decrement operators can
be applied before (prefix) or after
(postfix) the operand. The code
result++; and ++result; will both end
in result being incremented by one.
The only difference is that the prefix
version (++result) evaluates to the
incremented value, whereas the
postfix version (result++) evaluates
to the original value. If you are
just performing a simple
increment/decrement, it doesn't really
matter which version you choose. But
if you use this operator in part of a
larger expression, the one that you
choose may make a significant
difference.
To illustrate, try the following:
int x = 0;
int y = 0;
y = x++;
System.out.println(x);
System.out.println(y);
Which will print 1 and 0.
You don't really need the machine code to understand what's happending.
According the definitions:
The assignment operator evaluates the right-hand side expression, and stores it in a temporary variable.
1.1. The current value of x is copied into this temporary variable
1.2. x is incremented now.
The temporary variable is then copied into the left-hand side of the expression, which is x by chance! So that's why the old value of x is again copied into itself.
It is pretty simple.
You're effectively getting the following behavior.
grab the value of x (which is 0) as "the result" of the right side
increment the value of x (so x is now 1)
assign the result of the right side (which was saved as 0) to x (x is now 0)
The idea being that the post-increment operator (x++) increments that variable in question AFTER returning its value for use in the equation it's used in.
Edit: Adding a slight bit because of the comment. Consider it like the following.
x = 1; // x == 1
x = x++ * 5;
// First, the right hand side of the equation is evaluated.
==> x = 1 * 5;
// x == 2 at this point, as it "gave" the equation its value of 1
// and then gets incremented by 1 to 2.
==> x = 5;
// And then that RightHandSide value is assigned to
// the LeftHandSide variable, leaving x with the value of 5.
This is because it never gets incremented in this case. x++ will use the value of it first before incrementing like on this case it will be like:
x = 0;
But if you do ++x; this will increase.
The value stays at 0 because the value of x++ is 0. In this case it doesn't matter if the value of x is increased or not, the assignment x=0 is executed. This will overwrite the temporary incremented value of x (which was 1 for a "very short time").
This works how you expect the other one to. It's the difference between prefix and postfix.
int x = 0;
while (x < 3) x = (++x);
Think of x++ as a function call that "returns" what X was before the increment (that's why it's called a post-increment).
So the operation order is:
1: cache the value of x before incrementing
2: increment x
3: return the cached value (x before it was incremented)
4: return value is assigned to x
When the ++ is on the rhs, the result is returned before the number is incremented.
Change to ++x and it would have been fine.
Java would have optimised this to perform a single operation (the assignment of x to x) rather than the increment.
Well as far as I can see, the error occurs, due to the assignment overriding the incremented value, with the value prior to incrementation, i.e. it undoes the increment.
Specifically, the "x++" expression, has the value of 'x' prior to increment as opposed to "++x" which has the value of 'x' after incrementation.
If you are interested in investigating the bytecode, we will take a look at the three lines in question:
7: iload_1
8: iinc 1, 1
11: istore_1
7: iload_1 # Will put the value of the 2nd local variable on the stack
8: iinc 1,1 # will increment the 2nd local variable with 1, note that it leaves the stack untouched!
9: istore_1 # Will pop the top of stack and save the value of this element to the 2nd local variable
(You can read the effects of each JVM instruction here)
This is why the above code will loop indefinitely, whereas the version with ++x will not.
The bytecode for ++x should look quite different, as far as I remember from the 1.3 Java compiler I wrote a little over a year ago, the bytecode should go something like this:
iinc 1,1
iload_1
istore_1
So just swapping the two first lines, changes the semantics so that the value left on the top of stack, after the increment (i.e. the 'value' of the expression) is the value after the increment.
x++
=: (x = x + 1) - 1
So:
x = x++;
=> x = ((x = x + 1) - 1)
=> x = ((x + 1) - 1)
=> x = x; // Doesn't modify x!
Whereas
++x
=: x = x + 1
So:
x = ++x;
=> x = (x = x + 1)
=> x = x + 1; // Increments x
Of course the end result is the same as just x++; or ++x; on a line by itself.
x = x++; (increment is overriden by = )
because of above statement x never reaches 3;
I wonder if there's anything in the Java spec that precisely defines the behavior of this. (The obviously implication of that statement being that I'm too lazy to check.)
Note from Tom's bytecode, the key lines are 7, 8 and 11. Line 7 loads x into the computation stack. Line 8 increments x. Line 11 stores the value from the stack back to x. In normal cases where you are not assigning values back to themselves, I don't think there would be any reason why you couldn't load, store, then increment. You would get the same result.
Like, suppose you had a more normal case where you wrote something like:
z=(x++)+(y++);
Whether it said (pseudocode to skip technicalities)
load x
increment x
add y
increment y
store x+y to z
or
load x
add y
store x+y to z
increment x
increment y
should be irrelevant. Either implementation should be valid, I would think.
I'd be extremely cautious about writing code that depends on this behavior. It looks very implementation-dependent, between-the-cracks-in-the-specs to me. The only time it would make a difference is if you did something crazy, like the example here, or if you had two threads running and were dependent on the order of evaluation within the expression.
I think because in Java ++ has a higher precedence than = (assignment)...Does it?
Look at http://www.cs.uwf.edu/~eelsheik/cop2253/resources/op_precedence.html...
The same way if you write x=x+1...+ has a higher precedence than = (assignment)
The x++ expression evaluates to x. The ++ part affect the value after the evaluation, not after the statement. so x = x++ is effectively translated into
int y = x; // evaluation
x = x + 1; // increment part
x = y; // assignment
Before incrementing the value by one, the value is assigned to the variable.
It's happening because it's post incremented. It means that the variable is incremented after the expression is evaluated.
int x = 9;
int y = x++;
x is now 10, but y is 9, the value of x before it was incremented.
See more in Definition of Post Increment.
Check the below code,
int x=0;
int temp=x++;
System.out.println("temp = "+temp);
x = temp;
System.out.println("x = "+x);
the output will be,
temp = 0
x = 0
post increment means increment the value and return the value before the increment. That is why the value temp is 0. So what if temp = i and this is in a loop (except for the first line of code). just like in the question !!!!
The increment operator is applied to the same variable as you are assigning to. That's asking for trouble. I am sure that you can see the value of your x variable while running this program.... that's should make it clear why the loop never ends.

Java vs C output

This might seem simple but it's just stumbled me and my friends...
lets take the following piece of code-
in java
//........
int a=10;
a= a-- + a--;
System.out.print("a="+a);
//........
in c
//........
int a=10;
a= a-- + a--;
printf("a= %d",a);
//.......
where in the former case you get output as 19 in C you get it as 18.
the logic in c is understandable but in java?
in java if its like
int a=10;
a=a++;
in this case the output is 10.
So what's the logic?
a = a-- + a-- causes undefined behaviour in C. C does not define which decrement should be evaluated first.
a-- evaluates to the value of a, and after that it decrements a,
so in Java a = a-- + a-- evaluates like this:
a = (10, decrement a) + (9, decrement a)
The second operand is 9 because first term caused a to be decremented.
In summary: With that expression, C does not define the evaluation order. Java defines it to be from left to right.
I don't know about Java but in C that line of code doesn't have a return value defined in the standard. Compilers are free to interpret it as they please.
In the expression
a = a-- + a--;
you have a lot of sub-expressions that need to be evaluated before the whole of the expression is evaluated.
a = a-- + a--;
^^^ <= sub-expression 2
^^^ <= sub-expression 1
What's the value of sub-expression 1? It's the current value of the object a.
What's the value of the object a?
If the sub-expression 2 was already evaluated, value of object a is 9, otherwise it is 10.
Same thing for sub-expression 2. Its value can be either 9 or 10, depending on whether sub-expression 1 was already evaluated.
The C compiler (don't know about Java) is free to evaluate the sub-expressions in any order
So let's say the compiler chose to leave the --s for last
a = 10 + 10;
a--; /* 19 */
a--; /* 18 */
but on the next compilation the compiler did the --s up front
/* value of sub-expression 1 is 10 */
/* value of sub-expression 2 is 9 */
a = 10 + 9; /* a = 9 + 10; */
or it could even save one of the a-- and use that for the final value of a
/* sub-expression 1 yields 10 and sets the value of `a` to 9 */
/* so yield that 10, but save the value for the end */
a = 10 + ???;
a = 18???; a = 19???;
/* remember the saved value */
a = 9
Or, as you invoked undefined behaviour, it could simply replace your statement with any of the following
a = 42;
/* */
fprintf(stderr, "BANG!");
system("format C:");
for (p=0; p<MEMORY_SIZE; p++) *p = 0;
etc ...
You are post-decrementing. To me, the java result makes more sense.
The first a-- is evaluated as 10, and decrements to 9. 10 is the value of this sub-expression.
The second a-- is evaluated. a is now 9, and decrements to 8. The value of this sub-expression is 9.
So, it becomes 10 + 9 = 19. The two decrements get overwritten by the assignment.
I'd expect 18 if the expression were a= --a + --a.
Have you tried compiling the C version with different optimization flags?
a= a-- + a--;
This invokes undefined behaviour in C/C++. You should not expect consistent results from this statement.
a = 10 + 9
you can try with:
a = a-- + a-- + a--
it returns 27 ( 10 + 9 + 8)...

Categories

Resources