Over the weekend I saw what I considered to be an interesting e-mail on one of the various mail alias I am subscribed to. This e-mail was basically titled 'Error in the Java compiler?' and said the following...
Hallo all,
Why do different results come out with the program 2? From my point of
view A and b must agree. The lines are semantically alike. The operator
++ binds more strongly than +
public class Main {
public static void main(String[] args) {
int b, a;
b = 2;
b = ++b+b;
a = 2;
a = a+++a;
System.out.println("b: " + b);
System.out.println("a: " + a);
}
}
Output:
run:
b: 6
a: 5
The answer to me was quite obvious. The user simply hadn't realised that a++ and ++a are different in so far as a++ will use the current value of a for whatever it is currently doing, then it will add 1 to a. ++a on the other hand will add 1 to a and then use the new value of a.
2+1 + 3
++b+b = b+1 + b = 6
2 + 3
a+++a = a++ + a = 5
However, it then turns out that the example provided wasn't really appropriate and as such the user sent a new e-mail, this time with the following example:
int b, a;
b = 2;
b = ++b*b; // this represent (2+1)*3 that's OK
a = 2;
a = a*++a; // ++a is 3, then is the first a also 3... but this a is 2...
System.out.println("b: " + b);
System.out.println("a: " + a);
Output:
run:
b: 9
a: 6
Naturally this again was not an error in the Java compiler. It was due to the Java specification which says that all expressions are evaluated from left to right. As such, in the second example we evaluate a to be 2 first, and then we times that by ++a, resulting in 6...
2+1 * 3
b = ++b * b = 9
2 * 2+1
a = a * ++a = 6
The most interesting thing about this whole subject is that if you were to write that kind of code in C it would be completely undefined in terms of what the results would be. The compiler writers may do their best to come up with sensible solutions, but some times you'll get 9, other times you'll get 6 and for that matter some times you could get -99,938 or even 2,394,343 etc.
So - what is the moral of all this - don't write code like that. Do it in two separate statements. That way the code is clearer and the outcome is more predictable.