First of all, expressions of the form a++ + ++a
, ++a + a++
, etc., result in undefined behavior; any result is possible. From the language standard (n1256):
6.5 Expressions
...
2 Between the previous and next sequence point an object shall have its stored value
modified at most once by the evaluation of an expression.72) Furthermore, the prior value
shall be read only to determine the value to be stored.73)
...
72) A floating-point status flag is not an object and can be set more than once within an expression.
73) This paragraph renders undefined statement expressions such as
i = ++i + 1;
a[i++] = i;
while allowing
i = i + 1;
a[i] = i;
So, don't do that.
A well-defined expression like x = a++ + ++b
will be parsed as x = ((a++) + (++b))
; both forms of the ++
operator have higher precedence than addition, and addition has higher precedence than assignment. The result of the expression will be the same as x = a + (b + 1)
.
Secondly, remember that the ++
and --
operators have a result and a side effect, as shown below:
Expression Result Side effect
---------- ------ -----------
i++ i i = i + 1
++i i + 1 i = i + 1
i-- i i = i - 1
--i i - 1 i = i - 1
Important note to remember: the side effect doesn't have to be applied immediately after the expression is evaluated; it only has to be applied before the next sequence point. It's possible for x = a++ + ++b
to be evaluated as follows:
t1 = a;
t2 = b + 1;
x = t1 + t2;
b = b + 1;
a = a + 1;
In this case, the updates to a
and b
are deferred until after the addition and assignment to x
.
As far as precedence is concerned, here is the general order from high to low:
- Postfix operators (all have the same precedence, so sequences of operators will be evaluated left-to-right)
- array subscript operator
[]
- function call operator
()
- component selection operators
.
and ->
- postfix
++
and --
- Unary operators (all have the same precedence, so sequences of operators will be evaluated left-to-right)
- prefix
++
and --
sizeof
- bitwise negation operator
~
- logical negation operator
!
- unary sign operators
-
and +
- address-of operator
&
- dereference operator
*
- Cast expressions
(
type name )
- Multiplicative operators
*
, /
, %
- Additive operators
+
and -
- Shift operators
<<
and >>
- Relational operators
<
, >
, <=
, >=
- Equality operators
==
and !=
- Bitwise AND
&
- Bitwise XOR
^
- Bitwise OR
|
- Logical AND
&&
- Logical OR
||
- Conditional operator
?:
- Assignment operators
=
, +=
. -=
, *=
, /=
, %=
, <<=
, >>=
, &=
, ^=
, |=
- Sequential (comma) operator
,
So, expressions like *x++
are parsed as *(x++)
, since the postfix ++
has higher precedence than the unary *
. Similarly, sizeof x + 1
is parsed as (sizeof x) + 1
, since sizeof
has higher precedence than addition. An expression like p++->x
is parsed as (p++)->x
; both postfix ++
and ->
operators have the same precedence, so they're parsed from left to right.
This is about as short as shortcuts get; when in doubt, use parentheses.