5

Why does the following given expression invoke undefined behavior?

int i = 5;
i = (i,i++,i) + 1 

My question is influenced by Als' question here

Community
  • 1
  • 1
McCoy
  • 59
  • 2

3 Answers3

11

It isn't undefined.

Answered here for C, Sequence points and partial order

I think the same applies in C++ (and here's my response before I saw that link):

The comma operator introduces a sequence point (and constrains to some extent the order in which the expression must be evaluated - left before right), so:

  • the two modifications of i are separated by a sequence point (the second comma).
  • the modification of i in i++ is separated from everything else by sequence points.
  • the modification of i by = is not separated from the last occurrence of i in the expression, but that's OK because we're allowed to access i and modify it without an intervening sequence point, provided that the access is "to determine the value to be stored" (5/4).
  • As Als says, in practice it wouldn't matter whether that code has defined behavior or not provided that everyone had the basic common sense not to write it ;-)
Community
  • 1
  • 1
Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
  • Considering only the fact that `,` is a sequence point, yes. Unfortunately the standard is very careful about this: `Note that some aspects of sequencing in the abstract machine are unspecified; the preceding restriction upon side effects applies to that particular execution sequence in which the actual code is generated.` – Šimon Tóth Nov 05 '10 at 11:55
  • I wanted to answer but I didn't. [Yet another undefined behaviour question] ;-) – Prasoon Saurav Nov 05 '10 at 11:56
  • @Let_Me_Be: I confess I don't understand that footnote. What does it mean for "actual code" to be generated "in an execution sequence"? – Steve Jessop Nov 05 '10 at 12:04
  • @Let_Me_Be: oh, I think I get it. The implementation has a choice of legal execution sequences for an expression, and which one it chooses is unspecified. The restrictions on side-effects mention terms like "previous" and "subsequent", and those terms are to be understood with respect to the order actually chosen. Right? So here we rely on two facts (1) that the side-effects are complete, and (2) that the comma operator specifies the order of execution of its operands (5.18/1: "All side effects [on the left] are performed before the evaluation of the right expression.") – Steve Jessop Nov 05 '10 at 12:17
  • Come to think of it, nothing explicitly states that the comma operator actually is a sequence point, only that all side effects on the left are complete. But the rules for expressions don't say you can modify twice if all side effects are complete, they say you can modify twice *if there's a sequence point*. However, the examples in 5/4 clearly treat comma as a sequence point, so I think we must conclude that it is one, on the basis that its semantics incorporate the semantics of a sequence point. – Steve Jessop Nov 05 '10 at 12:22
  • @Steve Well, yes, that is kind of how I understand it as well. The actual order is implementation defined (that includes the order between sequence points), but still should conform to the language definition (like the order of comma operands). – Šimon Tóth Nov 05 '10 at 12:24
  • @Steve `,` is a sequence point in C++ standard: `In the evaluation of each of the expressions {a && b} {a || b} {a ? b : c} {a , b} using the built-in meaning of the operators in these expressions (5.14, 5.15, 5.16, 5.18), there is a sequence point after the evaluation of the first expression.` – Šimon Tóth Nov 05 '10 at 12:26
  • @Let_Me_Be: oh good, that makes it simpler. I missed that because my flipping PDF reader's text search can't find matches across a page boundary. That's annoying. – Steve Jessop Nov 05 '10 at 12:27
  • To me this is all a big mess in C++03. Notice the exact wording of this: "At certain specified points in the execution sequence called sequence points, all side effects of previous evaluations shall be complete and no side effects of subsequent evaluations shall have taken place" - when evaluating the right operand of op=, the evaluation of op= have already begun, so I think it can't be strongly followed from this that the side effects are sequenced, because op= is not clearly a "subsequent evaluation" relative to the evaluation of the right hand side of it. – Johannes Schaub - litb Nov 05 '10 at 17:36
  • In other words - in the word "fun", does the character "u" preceede or follow the word "fun"? – Johannes Schaub - litb Nov 05 '10 at 17:36
  • @litb: true, and I think you could likewise (although less convincingly) argue from the text that in `i = i + 1`, the side effect could preceed the evaluation of `i` on the rhs. It's the temporal nature of causality, and the examples given in the standard, rather than any text about sequence points, which says otherwise. I agree the definitions in the standard are a bit lacking. – Steve Jessop Nov 05 '10 at 17:53
  • @Steve for `i = i + 1` the assignment modification happens between the same pair of sequence points as the read of `i`, but that's allowed because the read is "to determine the value to be stored.". – Johannes Schaub - litb Nov 05 '10 at 21:03
  • @SteveJessop: Requiring a sequence point between reading the RHS and writing the LHS of `i=i+1` would make it *much* slower on some machines, especially if `i` is longer than a machine word. Each portion of `i` must be read before it is written, but it's possible to read the lowest byte, write the lowest byte, read the next byte, write the next byte, etc. rather than having to read everything, perform the computation, and write everything. – supercat Jul 09 '15 at 19:48
0

Because it isn't defined in the standard which of the post-increment or the assignment will take place first; it is left to the compiler implementation to decide their order.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
0

It is undefined in C++ to assign an incremented value to itself:

i = i++

What should i be after this? Should it be the previous value or one plus the previous value? The order of execution is left to the compiler, so different platforms will have different results.

chrisaycock
  • 36,470
  • 14
  • 88
  • 125
  • I'm pretty sure that `i` should remain unchanged after that. It's still technically undefined behavior because of the sequence point thing, but there's no way there could be some other result. – Paul Manta Dec 03 '11 at 09:08