As per C++11 1.9 Program execution /15:

Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced.

If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined.

In this case, I believe ++x is a side effect and x %= 10 is a value computation so you'd think it would be undefined behaviour. However, the assignment section (5.17 /1) has this to say (my bold):

In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression.

Hence that means that both sides are sequenced before the assignment and before the result of the assignment is made available. And since the standard also states (5.17 /7) that x OP = y is identical to x = x OP y but with x only being evaluated once, it turns out this is well defined behaviour, as it's equivalent to:

++x = Q % 10; // where Q is the value from ++x, not evaluated again.

The only question then remains is which side of the assignment is evaluated since they're not sequenced. However, I don't think it matters in this case since both these will have the same effect:

++x = Q % 10; // LHS evaluated first
Q = ++x % 10; // RHS evaluated first

Now, that's my reading of the standard. While I have a fair amount of experience in decoding complex documents, there may be something I've missed - I don't think so because we've all had a lively discussion here in getting to this point :-) and I think we've all established the relevant sections.

But, regardless of whether it's wel defined or not, decent coders shouldn't be writing code like that. It's been a long time since the low-memory/small-storage days of the PDP minis, it's about time we wrote our code to be readable.

If you want to increment then take the modulo, use x = (x + 1) % 10, if only to make it easier to understand for the next poor Joe reading that code.


TL;DR: It is well-defined because x is guaranteed to be incremented before the assignment.


Some C++11 standardese

[intro.execution]/15:

Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced.

However, [expr.ass]/1 does note something:

In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression.

So this does constitute an exception to the first quote. Moreover, as stated in [expr.pre.incr]1, ++x is equivalent to x += 1, which is also covered by the above quote: The assignment is sequenced before the value computation. Thus for ++x the increment is sequenced before the value computation.

Taking that into account it is not hard to see that in ++x %= 10, the increment is done before the assignment is.
So the increment side-effect is sequenced before the assignment side-effect, and thus all involved side-effects are sequenced.

To put it in another way, the standard imposes the following sequencing:

  • ++x and 10 are evaluated - the order of which is unsequenced, but 10 is just a literal so that's not relevant here.
    • ++x is evaluated:
      • First, the value of x is incremented.
      • Then the value computation is done, and we get an lvalue referring to x.
  • The assignment is done. The updated value of x is taken modulo 10 and assigned to x.
  • The value computation of the assignment might follow, which is clearly sequenced after the assignment.

Hence

If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined.

doesn't apply as the side-effects and value-computations are sequenced.


1 Not [expr.post.incr] which would be for the postfix increment!