Evaluation of precedence and evaluation of side effects are NOT synchronised in any way. Read the FAQ and try to get to grips with "before", "after" and "sequence points".
If you believe that given
a * b + ++c;
that the increment of c only happens between the multiply of a*b and before the addition of the modified value of c, then you're very much mistaken. The language makes no such guarantees about such behaviour, and if you assume it does, you're going to get burned.
Simply saying "this works for me" is no substitute for understanding these basic rules. And if you don't understand them, then you're laying yourself open to being burnt with some pretty obscure effects if you use them in a large program.
Now whilst the FAQ I posted refers to C, you can be sure that the same rules apply to C++ as well.
And now, some results from the test program.
Code:
$ gcc -W -Wall -ansi -pedantic -O2 foo.c
foo.c: In function `main':
foo.c:7: warning: operation on `a' may be undefined
foo.c:8: warning: operation on `a' may be undefined
foo.c:9: warning: operation on `a' may be undefined
foo.c:10: warning: operation on `a' may be undefined
$ ./a.exe
Pre: f(++a, a) --> 2 1
f(a, ++a) --> 2 2
Post: f(a++, a) --> 1 1
f(a, a++) --> 2 1
$ gcc -W -Wall -ansi -pedantic -O3 foo.c
foo.c: In function `main':
foo.c:7: warning: operation on `a' may be undefined
foo.c:8: warning: operation on `a' may be undefined
foo.c:9: warning: operation on `a' may be undefined
foo.c:10: warning: operation on `a' may be undefined
$ ./a.exe
Pre: f(++a, a) --> 2 2
f(a, ++a) --> 1 2
Post: f(a++, a) --> 1 2
f(a, a++) --> 1 1
Well how about that then!?
Changing the optimisation level changes the results.
Which is pretty obvious really. The compiler warned about possible undefined operations, and it came through in spades with different results.
Optimisation does not affect the results of a correct program, but will generally play havoc with an undefined program.
Lets try with VC6
Code:
> cl /nologo foo.c
foo.c
> foo.exe
Pre: f(++a, a) --> 2 1
f(a, ++a) --> 2 2
Post: f(a++, a) --> 1 1
f(a, a++) --> 1 1
> cl /O2 /nologo foo.c
foo.c
> foo.exe
Pre: f(++a, a) --> 2 2
f(a, ++a) --> 2 2
Post: f(a++, a) --> 1 2
f(a, a++) --> 2 1
Wow, even more fun from the broken code.
4 different compilations, 4 different sets of results. This is NOT GOOD CODE.
That is, after all, what my signature line means.