5

Similar codes for example (a+=1)%=7;, where a is an int variable.

We know that operator += or = is not a sequence point, therefore we have two side-effects between two adjcent sequence points. (we are using cpp98's sequence point rules here)

However, assignment operators like += or = guarantees to return the lvalue after assignment, which means the order of execution is to some degree "defined".

So is that an undefined behaviour ?

curiousguy
  • 8,038
  • 2
  • 40
  • 58
inverse
  • 145
  • 5
  • I think the parentheses prevent your titular expression from being undefined behaviour. However, if you were to have: `int a = 2; (a = 1) = a;` then that **is** undefined (as `clang-cl` has it: "unsequenced modification and access to 'a'"). – Adrian Mole Apr 01 '20 at 04:14
  • Short answer is yes, the behaviour is undefined. In C++98, parentheses do not give a sequence point, and modifying a variable twice between two sequence points - i.e. the `+=` and `%=` operators will both modify `a` - gives undefined behaviour. – Peter Apr 01 '20 at 04:17

1 Answers1

5

(a=1)=2 was undefined prior to C++11, as the = operator did not introduce a sequence point and therefore a is modified twice without an intervening sequence point. The same applies to (a+=1)%=7

The text was:

Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression.

It's worth mentioning that the description of the assignment operator is defective:

The result of the assignment operation is the value stored in the left operand after the assignment has taken place; the result is an lvalue.

If the result is an lvalue then the result cannot be the stored value (that would be an rvalue). Lvalues designate memory locations. This sentence seems to imply an ordering relation, but regardless of how we want to interpret it, it doesn't use the term "sequence point" and therefore the earlier text about sequence points applies.

If anything, that wording casts a bit of doubt on expressions like (a=1) + 2. The C++11 revision of sequencing straightened out all these ambiguities.

M.M
  • 138,810
  • 21
  • 208
  • 365
  • When the standards were first written, nobody thought anyone would care about whether the Standard actually defined a corner case that compilers consistently processed the same way and where there was no imagined benefit to doing anything else, unless a situation arose where doing something else would offer a significant and unanticipated benefit. In that case, having the behavior defined would preclude the possibility of realizing the benefit in question, while leaving it undefined would allow the implementer to weigh the costs and benefits of common versus alternative behaviors. – supercat Apr 02 '20 at 17:23
  • @supercat did compilers consistently process `(a=1)=2` ? – M.M Apr 02 '20 at 23:48
  • Did any compilers that processed `(a=1)` as a non-const lvalue do anything other than store the 1 before processing the second assignment? – supercat Apr 03 '20 at 00:08
  • @supercat i'm asking you , you're the one claiming that compilers consistently processed these the same way – M.M Apr 03 '20 at 00:08