TITLE: sequence points and chained assignment (Newsgroups: comp.lang.c++, 28 Jan 97) KUEHL: kuehl@uzwil.informatik.uni-konstanz.de (Dietmar Kuehl) : > Thank you for trying to defend my statement but... no, the result of : > '(x = 6) = y' is indeed undefined behavior if 'x' is an 'int' and 'y' : > is convertible to 'int': It would result in an object modified twice : > between sequence points. This always results in undefined behavior... [...deleted...] BLACK: Paul Black (paul.black@vf.vodafone.co.uk) : But there is a sequence point: the side effects of "x = 6" are complete : and none of the side effects of the subsequent evaluation "() = y" have : taken place (see section 1.8 of the draft standard). KUEHL: In the expression '(x = 6) = y;' I can see only one sequence pointer, namely the one at the end of the full expression: Neither assignment nor parenthesis add a sequence point and there is no other condition which would add one. Thus, the object 'x' is modified twice between sequence points. I looked through section 1.8 but did not find anything which would add a sequence point there. Maybe I have missed the clause. In this case, please direct me to the corresponding section. (Newsgroups: comp.lang.c++, 31 Jan 97) BLACK: :> : The bit I'm thinking of is paragraph 7: :> : | 7 Accessing an object designated by a volatile lvalue (_basic.lval_), :> : | modifying an object, calling a library I/O function, or calling a :> : | function that does any of those operations are all side effects, which :> : | are changes in the state of the execution environment. Evaluation of :> : | an expression might produce side effects. 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 subse- :> : | quent evaluations shall have taken place. :> : My interpretation is: using the phrase "Evaluation of an expression", :> : I'm regarding "x = 6" as an expression in it's own right (the grammar in :> : Section 5.1 of the draft shows a primary expression as "( expression )"). :> : Therefore when the "x = 6" is evaluted, all of the side effects have :> : completed before any side effects of "() = y". KUEHL: :> There is nothing said in this paragraph that the produced side effects :> are finished at the end of an expression. In fact, an expression does :> not introduce a sequence point. What does introduce a sequence point is :> a "full expression". A full expression is the maximum unit which is an :> expression. Examples are simple statements made up only of an :> expression and conditionals. However, in '(x = 6) = y' the part 'x = 6' :> is definitely not a full expression and hence no sequence point is :> introduced but one modification of 'x' took place. With '() = y' :> another modification of 'x' happens -> undefined behavior. BLACK: : But the "x = 6" has finished before the "() = y", section 5.17: : "The result of the assignment operation is the value stored in the left : operand after the assignment has taken place;" KUEHL: Changing the value of 'x' to become '6' is clearly a side effect as described in the portion of the DWP cited above. The exact time when side effects are actually done is not determined by the expression itself but rather by the corresponding sequence point (also stated in the section cited above). Thus, you have to look for sequence points and this is all: Only at sequence points objects are in a well defined state. The reason this is so is to allow some very important optimizations which would otherwise be impossible. Also, whether the assignment is finished or not is absolutely irrelevant: Modifying an object twice between sequence points is undefined behavior (clearly stated in the DWP). The situations where sequence points are introducde are well defined. '(x = 6) = y' does not contain a sequence point (except at the end of the expression) and thus 'x' would be modified twice between sequence points. Hence, '(x = 6) = y' results in undefined behavior: There is no room for interpretation.