In C operation associativity is as such for increment, decrement and assignment.
2. postfix ++ and --
3. prefix ++ and --
16. Direct assignment =
<
As AndreyT already pointed out, precedence and associativity don't tell you about order of evaluation. They only tell you about grouping. For example, precedence is what tells use that a*b+c
is grouped as (a*b)+c
instead of a*(b+c)
. The compiler is free to evaluate a
, b
and c
in any order it sees fit with either of those expressions. Associativity tells you about grouping when you have operators of the same precedence, most often, the same operators. For example, it's what tells you that a-b-c
is equivalent to (a-b)-c
, not a-(b-c)
(otherwise stated, subtraction is left associative).
Order of evaluation is defined by sequence points. There's a sequence point at the end of a full expression (among other things). At the sequence point, all the previous evaluations have to have taken place, and none of the subsequent evaluations can have taken place yet.
Looking at your specific examples, in a=b++;
, the result is mostly from the definition of post-increment itself. A post-increment yields the previous value of the variable, and sometime before the next sequence point, the value of that variable will be incremented. A pre-increment yields the value of the variable with the increment applied. In neither case, however, does that mean the variable has to be incremented in any particular order relative to the assignment. For example, in your pre-increment example, the compiler is entirely free to do something equivalent to:
temp = b+1;
a = temp;
b = b + 1;
Likewise, in the post-increment version, the variable can be incremented before or after the assignment:
a = b;
b = b + 1;
or:
temp = b;
b = b + 1;
a = temp;
Either way, however, the value assigned to a
must be the value of b
before it's incremented.
Operator precedence and associativity does not tell you what happens before and what happens after. Operator precedence/associativity has nothing to do with it. In C language temporal relationships like "before" or "after" are defined by so called sequence points and only by sequence points (and that's a totally separate story).
Operator precedence/associativity simply tells you which operands belong to which operators. For example, the expression a = b++
can be formally interpreted as (a = b)++
and as a = (b++)
. Operator precedence/associativity is this case simply tells you that the latter interpretation is correct and the former is incorrect (i.e. ++
applies to b
and not to the result of a = b
).
That, once again, does not mean that b
should be incremented first. Operator precedence/associativity, once again, has noting to do with what happens "first" and what happens "next". It simply tells you that the result of b++
expression is assigned to a
. By definition, the result of b++
(postfix increment) is the original value of b
. This is why a
will get the original value of b
, which is 1. When the variable b
will get incremented is completely irrelevant, as long as a
gets assigned b
's original value. The compiler is allowed to evaluate this expression in any order and increment b
at any time: anything goes, as long as a
somehow gets the original value of b
(and nobody really cares how that "somehow" works internally).
For example, the compiler can evaluate a = b++
as the following sequence of elementary operations
(1) a := b
(2) b := b + 1
or it can evaluate it as follows
(1) b := b + 1
(2) a = b - 1
Note that in the first case b
is actually incremented at the end, while in the second case b
is incremented first. But in both cases a
gets the same correct value - the original value of b
, which is what it should get.
But I have to reiterate that the above two examples are here just for illustrative purposes. In reality, expressions like a = ++b
and a = b++
have no sequence points inside, which means that from your point of view everything in these expressions happens simultaneously. There's no "before", "after", "first", "next" or "last". Such expressions are "atomic" in a sense that they cannot be meaningfully decomposed into a sequence of smaller steps.
The postfix operator a++
will increment a
and then return the original value i.e. similar to this:
{ temp=a; a=a+1; return temp; }
and the prefix ++a
will return the new value i.e.
{ a=a+1; return a; }
This is irrelevant to the operator precedence.
(And associativity governs whether a-b-c
equals to (a-b)-c
or a-(b-c)
.)