behaviour of (i++)%3 vs. (++i)%3

Using gcc on x86 (version 4.7.2) I find the following:

a=(++a)%3 gives: 0,1,2,0,1,2,0,....
a=(a++)%3 gives: 1,2,3,1,2,3,1.....

which, to me, was a little surprising. I thought they both would give 0,1,2...
On Arduino with avr-g++ (otherwise the same compiler) I get:

a=(++a)%3 gives: 0,1,2,0,1,2,0,.... same as for x86
a=(a++)%3 gives: 0,1,2,3,4,5,6,7,8,9,10....

which is even more surprising.
Can anyone explain why? Is it because of a difference in gcc and avr-g++, or does it have something to do with the options Arduino provides? I can see it may be due to some optimizing option... but I have tried all the Arduino options on the gcc compiler too and nothing changes.

Is the "a" signed or unsigned??

Using gcc on x86 (version 4.7.2) I find the following:

a=(++a)%3 gives: 0,1,2,0,1,2,0,....
a=(a++)%3 gives: 1,2,3,1,2,3,1.....

which, to me, was a little surprising. I thought they both would give 0,1,2...

I'm not sure why you thought that. There is a big difference in the pre- and post- increment operators, and the value that they return. See: http://arduino.cc/en/Reference/Increment

On Arduino with avr-g++ (otherwise the same compiler) I get:

a=(++a)%3 gives: 0,1,2,0,1,2,0,.... same as for x86
a=(a++)%3 gives: 0,1,2,3,4,5,6,7,8,9,10....

which is even more surprising.

You'd need to post a complete program. What you say you get is not logical.

The value of the expression "a++" is "a" and then "a" is incremented. With "++a" the increment is performed first and then the value of the expression is the incremented result.

I don't know how a=(a++)%3 could result in a value greater than two.

Pete

Modulo with a signed int value is tricky.

void setup()
{
Serial.begin(57600);
}

int a;

void loop()
{
a = (a++)%3;
Serial.println(a);
}

I can make a signed or unsigned.

janbor:
a=(a++)%3 gives: 0,1,2,3,4,5,6,7,8,9,10....

I don't think the language specification defines the behaviour, so it's ambiguous whether = assignment operator executes before or after the post increment. In this case it's up to the compiler whether it executes:

cache the value of a
calculate a%3
assign the result to a
increment the cached value
save the incremented value to a

or

calculate a%3 and cache the result
increment a
assign the cached result to a

(There are probably other legitimate interpretations, too.)

Any post-increment operator in an expression which also modifies the variable being incremented is dangerous.

Any post-increment operator in an expression which also modifies the variable being incremented is dangerous.

Yes clearly. I do wonder why gcc on x86 gives a different result from avr-g++ on AtMega328p though.

janbor:
I do wonder why gcc on x86 gives a different result from avr-g++ on AtMega328p though.

The behaviour is unspecified so each compiler can implement whatever behaviour it prefers. There's no reason why different compilers should choose the same behaviour.

There's no reason why different compilers should choose the same behaviour.

Well, that's the thing. It is the same compiler: Gnu gcc 4.7.2

Also, what do you mean "unspecified". I think quite a few would be surprised that the code:

loop and do a=(a++)%3; gives the result 0,1,2,3,4,5,6... completely ignoring the modulo.

You'd be surprised how many aspects of a vendor's implementation of C are left up to the vendor and are "unspecified". I can't begin to tell you how many chunks of code I've seen that assume the null termination characters, '\0' or null, for a string is the same as binary zero. However, the X3J11 standard for C leaves the definition of the null termination character up to the vendor.

janbor:
I think quite a few would be surprised that the code:

loop and do a=(a++)%3; gives the result 0,1,2,3,4,5,6... completely ignoring the modulo.

No doubt, but that's why code like this is so dangerous - it's actually legitimate for the compiler to evaluate the whole expression, update a and then over-write it with the original value plus one. Any expectations you might have about what it 'ought' to do are just wishful thinking - the actual behaviour is undefined.

This is worse than unspecified, it is undefined. The compiler can do anything including "make flying monkeys come out your butt."

The prioblem is that you are modifying 'a' twice between sequence points, which is a big no no.

http://c-faq.com/expr/evalorder1.html