views:

502

answers:

3

In C operation associativity is as such for increment, decrement and assignment.

  2. postfix ++ and -- 
  3. prefix ++ and -- 
  16. Direct assignment = 

The full list is found here Wikipedia Operators in C

My question is when we have

int a, b;

b = 1;
a = b++;

printf("%d", a); // a is equal to 1

b = 1;
a = ++b;

printf("%d", a); //a is equal to 2

Why is a equal to 1 with b++ when the postfix increment operator should happen before the direct assignment?

And why is the prefix increment operator different than the postfix when they are both before the assignment?

I'm pretty sure I don't understand something very important when it comes to operation associativity.

+7  A: 

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).)

KennyTM
+3  A: 

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.

AndreyT
`Operator associativity simply tells you which operands belong to which operators`...... Operator precedence tells that ..not operator associativity. Operator associativity comes into play when we have operators having same precedence. In this case `++` has higher precedence than `=` hence `a=b++` is interpreted as `a=(b++)`
Prasoon Saurav
@Prasoon Saurav: Whenever operator associativity "comes into play", it still tells you which operands belong to which operators. In fact, C language has no "operator precedence" and "operator associativity". You will not find anything like that in the standard. C language has a grammar, which defined everythihg. "Associativity" and "precedence" is nothing but an attempt to present the rules of grammar in more readable form. Both associativity and precedence have the same roots and do the same thing.
AndreyT
@AndreyT: I appreciate your views. `For example, the expression a = b++ can be formally interpreted as (a = b)++ and as a = (b++)` and thats because of operator precedence not because of operator associativity.
Prasoon Saurav
Ohh I didn't see your edit before posting the second comment. :-)
Prasoon Saurav
@Prasoon Saurav: I didn't want to repeat the terms "associativity and precedence" every time again and again, so I only used them together in the first sentence, and then just said "associativity" for brevity (since this is the term the OP was using). Now I gave in and edited it to say "associativity/precedence" every time...
AndreyT
+1  A: 

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.

Jerry Coffin