Undefined behavior and sequence points












930















What are "sequence points"?



What is the relation between undefined behaviour and sequence points?



I often use funny and convoluted expressions like a[++i] = i;, to make myself feel better. Why should I stop using them?



If you've read this, be sure to visit the follow-up question Undefined behavior and sequence points reloaded.



(Note: This is meant to be an entry to Stack Overflow's C++ FAQ. If you want to critique the idea of providing an FAQ in this form, then the posting on meta that started all this would be the place to do that. Answers to that question are monitored in the C++ chatroom, where the FAQ idea started out in the first place, so your answer is very likely to get read by those who came up with the idea.)










share|improve this question





























    930















    What are "sequence points"?



    What is the relation between undefined behaviour and sequence points?



    I often use funny and convoluted expressions like a[++i] = i;, to make myself feel better. Why should I stop using them?



    If you've read this, be sure to visit the follow-up question Undefined behavior and sequence points reloaded.



    (Note: This is meant to be an entry to Stack Overflow's C++ FAQ. If you want to critique the idea of providing an FAQ in this form, then the posting on meta that started all this would be the place to do that. Answers to that question are monitored in the C++ chatroom, where the FAQ idea started out in the first place, so your answer is very likely to get read by those who came up with the idea.)










    share|improve this question



























      930












      930








      930


      579






      What are "sequence points"?



      What is the relation between undefined behaviour and sequence points?



      I often use funny and convoluted expressions like a[++i] = i;, to make myself feel better. Why should I stop using them?



      If you've read this, be sure to visit the follow-up question Undefined behavior and sequence points reloaded.



      (Note: This is meant to be an entry to Stack Overflow's C++ FAQ. If you want to critique the idea of providing an FAQ in this form, then the posting on meta that started all this would be the place to do that. Answers to that question are monitored in the C++ chatroom, where the FAQ idea started out in the first place, so your answer is very likely to get read by those who came up with the idea.)










      share|improve this question
















      What are "sequence points"?



      What is the relation between undefined behaviour and sequence points?



      I often use funny and convoluted expressions like a[++i] = i;, to make myself feel better. Why should I stop using them?



      If you've read this, be sure to visit the follow-up question Undefined behavior and sequence points reloaded.



      (Note: This is meant to be an entry to Stack Overflow's C++ FAQ. If you want to critique the idea of providing an FAQ in this form, then the posting on meta that started all this would be the place to do that. Answers to that question are monitored in the C++ chatroom, where the FAQ idea started out in the first place, so your answer is very likely to get read by those who came up with the idea.)







      c++ undefined-behavior c++-faq sequence-points






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited May 23 '17 at 12:10


























      community wiki





      15 revs, 7 users 36%
      unknown

























          5 Answers
          5






          active

          oldest

          votes


















          645














          C++98 and C++03



          This answer is for the older versions of the C++ standard. The C++11 and C++14 versions of the standard do not formally contain 'sequence points'; operations are 'sequenced before' or 'unsequenced' or 'indeterminately sequenced' instead. The net effect is essentially the same, but the terminology is different.





          Disclaimer : Okay. This answer is a bit long. So have patience while reading it. If you already know these things, reading them again won't make you crazy.



          Pre-requisites : An elementary knowledge of C++ Standard





          What are Sequence Points?



          The Standard says




          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. (§1.9/7)




          Side effects? What are side effects?



          Evaluation of an expression produces something and if in addition there is a change in the state of the execution environment it is said that the expression (its evaluation) has some side effect(s).



          For example:



          int x = y++; //where y is also an int


          In addition to the initialization operation the value of y gets changed due to the side effect of ++ operator.



          So far so good. Moving on to sequence points. An alternation definition of seq-points given by the comp.lang.c author Steve Summit:




          Sequence point is a point in time at which the dust has settled and all side effects which have been seen so far are guaranteed to be complete.






          What are the common sequence points listed in the C++ Standard ?



          Those are:




          • at the end of the evaluation of full expression (§1.9/16) (A full-expression is an expression that is not a subexpression of another expression.)1


          Example :



          int a = 5; // ; is a sequence point here




          • in the evaluation of each of the following expressions after the evaluation of the first expression(§1.9/18) 2





            • a && b (§5.14)

            • a || b (§5.15)

            • a ? b : c (§5.16)


            • a , b (§5.18) (here a , b is a comma operator; in func(a,a++) , is not a comma operator, it's merely a separator between the arguments a and a++. Thus the behaviour is undefined in that case (if a is considered to be a primitive type))




          • at a function call (whether or not the function is inline), after the evaluation of all function arguments (if any) which
            takes place before execution of any expressions or statements in the function body (§1.9/17).



          1 : Note : the evaluation of a full-expression can include the evaluation of subexpressions that are not lexically
          part of the full-expression. For example, subexpressions involved in evaluating default argument expressions (8.3.6) are considered to be created in the expression that calls the function, not the expression that defines the default argument



          2 : The operators indicated are the built-in operators, as described in clause 5. When one of these operators is overloaded (clause 13) in a valid context, thus designating a user-defined operator function, the expression designates a function invocation and the operands form an argument list, without an implied sequence point between them.





          What is Undefined Behaviour?



          The Standard defines Undefined Behaviour in Section §1.3.12 as




          behaviour, such as might arise upon use of an erroneous program construct or erroneous data, for which this International Standard imposes no requirements 3.



          Undefined behaviour may also be expected when this
          International Standard omits the description of any explicit definition of behavior.




          3 : permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or with-
          out the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).



          In short, undefined behaviour means anything can happen from daemons flying out of your nose to your girlfriend getting pregnant.





          What is the relation between Undefined Behaviour and Sequence Points?



          Before I get into that you must know the difference(s) between Undefined Behaviour, Unspecified Behaviour and Implementation Defined Behaviour.



          You must also know that the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified.



          For example:



          int x = 5, y = 6;

          int z = x++ + y++; //it is unspecified whether x++ or y++ will be evaluated first.


          Another example here.





          Now the Standard in §5/4 says




          • 1) 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.


          What does it mean?



          Informally it means that between two sequence points a variable must not be modified more than once.
          In an expression statement, the next sequence point is usually at the terminating semicolon, and the previous sequence point is at the end of the previous statement. An expression may also contain intermediate sequence points.



          From the above sentence the following expressions invoke Undefined Behaviour:



          i++ * ++i;   // UB, i is modified more than once btw two SPs
          i = ++i; // UB, same as above
          ++i = 2; // UB, same as above
          i = ++i + 1; // UB, same as above
          ++++++i; // UB, parsed as (++(++(++i)))

          i = (i, ++i, ++i); // UB, there's no SP between `++i` (right most) and assignment to `i` (`i` is modified more than once btw two SPs)


          But the following expressions are fine:



          i = (i, ++i, 1) + 1; // well defined (AFAIK)
          i = (++i, i++, i); // well defined
          int j = i;
          j = (++i, i++, j*i); // well defined





          • 2) Furthermore, the prior value shall be accessed only to determine the value to be stored.


          What does it mean? It means if an object is written to within a full expression, any and all accesses to it within the same expression must be directly involved in the computation of the value to be written.



          For example in i = i + 1 all the access of i (in L.H.S and in R.H.S) are directly involved in computation of the value to be written. So it is fine.



          This rule effectively constrains legal expressions to those in which the accesses demonstrably precede the modification.



          Example 1:



          std::printf("%d %d", i,++i); // invokes Undefined Behaviour because of Rule no 2


          Example 2:



          a[i] = i++ // or a[++i] = i or a[i++] = ++i etc


          is disallowed because one of the accesses of i (the one in a[i]) has nothing to do with the value which ends up being stored in i (which happens over in i++), and so there's no good way to define--either for our understanding or the compiler's--whether the access should take place before or after the incremented value is stored. So the behaviour is undefined.



          Example 3 :



          int x = i + i++ ;// Similar to above




          Follow up answer for C++11 here.






          share|improve this answer





















          • 45





            *p++ = 4 isn't Undefined Behaviour . *p++ is interpreted as *(p++). p++ returns p(a copy) and the value in stored at the previous address. Why would that invoke UB? It is perfectly fine.

            – Prasoon Saurav
            Nov 14 '10 at 6:23








          • 6





            @Mike: AFAIK, there are no (legal) copies of the C++ Standard you could link to.

            – sbi
            Nov 14 '10 at 9:19






          • 10





            Well, then you could have a link to the ISO's relevant order page. Anyway, thinking about it, the phrase "elementary knowledge of C++ Standard" seems a bit of a contradiction in terms, since if you're reading the standard, you're past the elementary level. Maybe we could list what things in the language you need a basic understanding of, like expression syntax, order of operations, and maybe operator overloading?

            – Mike DeSimone
            Nov 14 '10 at 16:00






          • 37





            I'm not sure quoting the standard is the best way to teach newbies

            – Inverse
            Nov 14 '10 at 18:28






          • 6





            @Adrian The first expression invokes an UB because there is no sequence point between the last ++i and the assignement to i. The second expression does not invoke UB because expression i does not change the value of i. In the second example the i++ is followed by a sequence point (,) before the assignment operator is called.

            – Kolyunya
            Jul 1 '13 at 7:09





















          264














          This is a follow up to my previous answer and contains C++11 related material..





          Pre-requisites : An elementary knowledge of Relations (Mathematics).





          Is it true that there are no Sequence Points in C++11?



          Yes! This is very true.



          Sequence Points have been replaced by Sequenced Before and Sequenced After (and Unsequenced and Indeterminately Sequenced) relations in C++11.





          What exactly is this 'Sequenced before' thing?



          Sequenced Before(§1.9/13) is a relation which is:





          • Asymmetric

          • Transitive


          between evaluations executed by a single thread and induces a strict partial order1



          Formally it means given any two evaluations(See below)A and B, if A is sequenced before B, then the execution of A shall precede the execution of B. If A is not sequenced before B and B is not sequenced before A, then A and B are unsequenced 2.



          Evaluations A and B are indeterminately sequenced when either A is sequenced before B or B is sequenced before A, but it is unspecified which3.



          [NOTES]

          1 : A strict partial order is a binary relation "<" over a set P which is asymmetric, and transitive, i.e., for all a, b, and c in P, we have that:
          ........(i). if a < b then ¬ (b < a) (asymmetry);

          ........(ii). if a < b and b < c then a < c (transitivity).

          2 : The execution of unsequenced evaluations can overlap.

          3 : Indeterminately sequenced evaluations cannot overlap, but either could be executed first.





          What is the meaning of the word 'evaluation' in context of C++11?



          In C++11, evaluation of an expression (or a sub-expression) in general includes:




          • value computations (including determining the identity of an object for glvalue evaluation and fetching a value previously assigned to an object for prvalue evaluation) and


          • initiation of side effects.



          Now (§1.9/14) says:




          Every value computation and side effect associated with a full-expression is sequenced before every value computation and side effect associated with the next full-expression to be evaluated.






          • Trivial example:



            int x;
            x = 10;
            ++x;



            Value computation and side effect associated with ++x is sequenced after the value computation and side effect of x = 10;






          So there must be some relation between Undefined Behaviour and the above-mentioned things, right?



          Yes! Right.



          In (§1.9/15) it has been mentioned that




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




          For example :



          int main()
          {
          int num = 19 ;
          num = (num << 3) + (num >> 3);
          }



          1. Evaluation of operands of + operator are unsequenced relative to each other.

          2. Evaluation of operands of << and >> operators are unsequenced relative to each other.


          4: In an expression that is evaluated more than once during the execution
          of a program, unsequenced and indeterminately sequenced evaluations of its subexpressions need not be performed consistently in different evaluations.




          (§1.9/15)
          The value computations of the operands of an
          operator are sequenced before the value computation of the result of the operator.




          That means in x + y the value computation of x and y are sequenced before the value computation of (x + y).



          More importantly




          (§1.9/15) If a side effect on a scalar object is unsequenced relative to either



          (a) another side effect on the same scalar object



          or



          (b) a value computation using the value of the same scalar object.



          the behaviour is undefined.




          Examples:



          int i = 5, v[10] = { };
          void f(int, int);



          1. i = i++ * ++i; // Undefined Behaviour


          2. i = ++i + i++; // Undefined Behaviour

          3. i = ++i + ++i; // Undefined Behaviour

          4. i = v[i++]; // Undefined Behaviour

          5. i = v[++i]: // Well-defined Behavior

          6. i = i++ + 1; // Undefined Behaviour

          7. i = ++i + 1; // Well-defined Behaviour

          8. ++++i; // Well-defined Behaviour

          9. f(i = -1, i = -1); // Undefined Behaviour (see below)



          When calling a function (whether or not the function is inline), every value computation and side effect associated with any argument expression, or with the postfix expression designating the called function, is sequenced before execution of every expression or statement in the body of the called function. [Note: Value computations and side effects associated with different argument expressions are unsequenced. — end note]




          Expressions (5), (7) and (8) do not invoke undefined behaviour. Check out the following answers for a more detailed explanation.




          • Multiple preincrement operations on a variable in C++0x

          • Unsequenced Value Computations




          Final Note :



          If you find any flaw in the post please leave a comment. Power-users (With rep >20000) please do not hesitate to edit the post for correcting typos and other mistakes.






          share|improve this answer





















          • 3





            Instead of "asymmetric", sequenced before / after are "antisymmetric" relations. This should be changed in the text to conform to the definition of a partial order given later (which also agrees with Wikipedia).

            – TemplateRex
            Jul 21 '12 at 21:47






          • 1





            Why is 7) item in the last example an UB? Maybe it should be f(i = -1, i = 1)?

            – Mikhail
            Mar 18 '14 at 12:04






          • 1





            Here is the nice explanation: stackoverflow.com/a/21671069

            – Mikhail
            Mar 18 '14 at 12:16






          • 1





            I fixed the description of the "sequenced before" relation. It is a strict partial order. Obviously, an expression cannot be sequenced before itself, so the relation cannot be reflexive. Hence it is asymmetric not anti-symmetric.

            – ThomasMcLeod
            Jun 24 '14 at 20:52








          • 1





            5) being well befined blew my mind off. the explanation by Johannes Schaub wasn't entirely straightforward to get. Especially because I believed that even in ++i (being value evaluated before the + operator that is using it), the standard still doesn't say that its side effect must be finished. But in fact, because it returns an ref to a lvalue which is i itself, it MUST have finished the side effect since the evaluation must be finished, therefore the value must be up to date. This was the crazy part to get in fact.

            – v.oddou
            Jan 9 '15 at 6:31





















          19














          C++17 (N4659) includes a proposal Refining Expression Evaluation Order for Idiomatic C++
          which defines a stricter order of expression evaluation.



          In particular, the following sentence was added:




          8.18 Assignment and compound assignment operators:
          ....



          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.
          The right operand is sequenced before the left operand.




          It makes several cases of previously undefined behavior valid, including the one in question:



          a[++i] = i;


          However several other similar cases still lead to undefined behavior.



          In N4140:



          i = i++ + 1; // the behavior is undefined


          But in N4659



          i = i++ + 1; // the value of i is incremented
          i = i++ + i; // the behavior is undefined


          Of course, using a C++17 compliant compiler does not necessarily mean that one should start writing such expressions.






          share|improve this answer

































            11














            I am guessing there is a fundamental reason for the change, it isn't merely cosmetic to make the old interpretation clearer: that reason is concurrency. Unspecified order of elaboration is merely selection of one of several possible serial orderings, this is quite different to before and after orderings, because if there is no specified ordering, concurrent evaluation is possible: not so with the old rules. For example in:



            f (a,b)


            previously either a then b, or, b then a. Now, a and b can be evaluated with instructions interleaved or even on different cores.






            share|improve this answer





















            • 5





              I believe, though, that if either 'a' or 'b' includes a function call, they are indeterminately sequenced rather than unsequenced, which is to say that all side-effects from one are required to occur before any side-effects from the other, although the compiler need not be consistent about which one goes first. If that is no longer true, it would break a lot of code which relies upon the operations not overlapping (e.g. if 'a' and 'b' each set up, use, and take down, a shared static state).

              – supercat
              Dec 9 '10 at 20:35



















            0














            In C99(ISO/IEC 9899:TC3) which seems absent from this discussion thus far the following steteents are made regarding order of evaluaiton.




            [...]the order of evaluation of subexpressions and the order in which
            side effects take place are both unspecified. (Section 6.5 pp 67)



            The order of evaluation of the operands is unspecified. If an attempt
            is made to modify the result of an assignment operator or to access it
            after the next sequence point, the behavior[sic] is undefined.(Section
            6.5.16 pp 91)







            share|improve this answer





















            • 1





              The question is tagged C++ and not C, which is good because the behaviour in C++17 is quite different from the behaviour in older versions — and bears no relation to the behaviour in C11, C99, C90, etc. Or bears very little relation to it. On the whole, I'd suggest removing this. More significantly, we need to find the equivalent Q&A for C and make sure it is OK (and notes that C++17, in particular, changes the rules — the behaviour in C++11 and before was more or less the same as in C11, though the verbiage describing it in C still uses 'sequence points' whereas C++11 and later does not.

              – Jonathan Leffler
              Nov 30 '18 at 5:34



















            5 Answers
            5






            active

            oldest

            votes








            5 Answers
            5






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            645














            C++98 and C++03



            This answer is for the older versions of the C++ standard. The C++11 and C++14 versions of the standard do not formally contain 'sequence points'; operations are 'sequenced before' or 'unsequenced' or 'indeterminately sequenced' instead. The net effect is essentially the same, but the terminology is different.





            Disclaimer : Okay. This answer is a bit long. So have patience while reading it. If you already know these things, reading them again won't make you crazy.



            Pre-requisites : An elementary knowledge of C++ Standard





            What are Sequence Points?



            The Standard says




            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. (§1.9/7)




            Side effects? What are side effects?



            Evaluation of an expression produces something and if in addition there is a change in the state of the execution environment it is said that the expression (its evaluation) has some side effect(s).



            For example:



            int x = y++; //where y is also an int


            In addition to the initialization operation the value of y gets changed due to the side effect of ++ operator.



            So far so good. Moving on to sequence points. An alternation definition of seq-points given by the comp.lang.c author Steve Summit:




            Sequence point is a point in time at which the dust has settled and all side effects which have been seen so far are guaranteed to be complete.






            What are the common sequence points listed in the C++ Standard ?



            Those are:




            • at the end of the evaluation of full expression (§1.9/16) (A full-expression is an expression that is not a subexpression of another expression.)1


            Example :



            int a = 5; // ; is a sequence point here




            • in the evaluation of each of the following expressions after the evaluation of the first expression(§1.9/18) 2





              • a && b (§5.14)

              • a || b (§5.15)

              • a ? b : c (§5.16)


              • a , b (§5.18) (here a , b is a comma operator; in func(a,a++) , is not a comma operator, it's merely a separator between the arguments a and a++. Thus the behaviour is undefined in that case (if a is considered to be a primitive type))




            • at a function call (whether or not the function is inline), after the evaluation of all function arguments (if any) which
              takes place before execution of any expressions or statements in the function body (§1.9/17).



            1 : Note : the evaluation of a full-expression can include the evaluation of subexpressions that are not lexically
            part of the full-expression. For example, subexpressions involved in evaluating default argument expressions (8.3.6) are considered to be created in the expression that calls the function, not the expression that defines the default argument



            2 : The operators indicated are the built-in operators, as described in clause 5. When one of these operators is overloaded (clause 13) in a valid context, thus designating a user-defined operator function, the expression designates a function invocation and the operands form an argument list, without an implied sequence point between them.





            What is Undefined Behaviour?



            The Standard defines Undefined Behaviour in Section §1.3.12 as




            behaviour, such as might arise upon use of an erroneous program construct or erroneous data, for which this International Standard imposes no requirements 3.



            Undefined behaviour may also be expected when this
            International Standard omits the description of any explicit definition of behavior.




            3 : permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or with-
            out the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).



            In short, undefined behaviour means anything can happen from daemons flying out of your nose to your girlfriend getting pregnant.





            What is the relation between Undefined Behaviour and Sequence Points?



            Before I get into that you must know the difference(s) between Undefined Behaviour, Unspecified Behaviour and Implementation Defined Behaviour.



            You must also know that the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified.



            For example:



            int x = 5, y = 6;

            int z = x++ + y++; //it is unspecified whether x++ or y++ will be evaluated first.


            Another example here.





            Now the Standard in §5/4 says




            • 1) 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.


            What does it mean?



            Informally it means that between two sequence points a variable must not be modified more than once.
            In an expression statement, the next sequence point is usually at the terminating semicolon, and the previous sequence point is at the end of the previous statement. An expression may also contain intermediate sequence points.



            From the above sentence the following expressions invoke Undefined Behaviour:



            i++ * ++i;   // UB, i is modified more than once btw two SPs
            i = ++i; // UB, same as above
            ++i = 2; // UB, same as above
            i = ++i + 1; // UB, same as above
            ++++++i; // UB, parsed as (++(++(++i)))

            i = (i, ++i, ++i); // UB, there's no SP between `++i` (right most) and assignment to `i` (`i` is modified more than once btw two SPs)


            But the following expressions are fine:



            i = (i, ++i, 1) + 1; // well defined (AFAIK)
            i = (++i, i++, i); // well defined
            int j = i;
            j = (++i, i++, j*i); // well defined





            • 2) Furthermore, the prior value shall be accessed only to determine the value to be stored.


            What does it mean? It means if an object is written to within a full expression, any and all accesses to it within the same expression must be directly involved in the computation of the value to be written.



            For example in i = i + 1 all the access of i (in L.H.S and in R.H.S) are directly involved in computation of the value to be written. So it is fine.



            This rule effectively constrains legal expressions to those in which the accesses demonstrably precede the modification.



            Example 1:



            std::printf("%d %d", i,++i); // invokes Undefined Behaviour because of Rule no 2


            Example 2:



            a[i] = i++ // or a[++i] = i or a[i++] = ++i etc


            is disallowed because one of the accesses of i (the one in a[i]) has nothing to do with the value which ends up being stored in i (which happens over in i++), and so there's no good way to define--either for our understanding or the compiler's--whether the access should take place before or after the incremented value is stored. So the behaviour is undefined.



            Example 3 :



            int x = i + i++ ;// Similar to above




            Follow up answer for C++11 here.






            share|improve this answer





















            • 45





              *p++ = 4 isn't Undefined Behaviour . *p++ is interpreted as *(p++). p++ returns p(a copy) and the value in stored at the previous address. Why would that invoke UB? It is perfectly fine.

              – Prasoon Saurav
              Nov 14 '10 at 6:23








            • 6





              @Mike: AFAIK, there are no (legal) copies of the C++ Standard you could link to.

              – sbi
              Nov 14 '10 at 9:19






            • 10





              Well, then you could have a link to the ISO's relevant order page. Anyway, thinking about it, the phrase "elementary knowledge of C++ Standard" seems a bit of a contradiction in terms, since if you're reading the standard, you're past the elementary level. Maybe we could list what things in the language you need a basic understanding of, like expression syntax, order of operations, and maybe operator overloading?

              – Mike DeSimone
              Nov 14 '10 at 16:00






            • 37





              I'm not sure quoting the standard is the best way to teach newbies

              – Inverse
              Nov 14 '10 at 18:28






            • 6





              @Adrian The first expression invokes an UB because there is no sequence point between the last ++i and the assignement to i. The second expression does not invoke UB because expression i does not change the value of i. In the second example the i++ is followed by a sequence point (,) before the assignment operator is called.

              – Kolyunya
              Jul 1 '13 at 7:09


















            645














            C++98 and C++03



            This answer is for the older versions of the C++ standard. The C++11 and C++14 versions of the standard do not formally contain 'sequence points'; operations are 'sequenced before' or 'unsequenced' or 'indeterminately sequenced' instead. The net effect is essentially the same, but the terminology is different.





            Disclaimer : Okay. This answer is a bit long. So have patience while reading it. If you already know these things, reading them again won't make you crazy.



            Pre-requisites : An elementary knowledge of C++ Standard





            What are Sequence Points?



            The Standard says




            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. (§1.9/7)




            Side effects? What are side effects?



            Evaluation of an expression produces something and if in addition there is a change in the state of the execution environment it is said that the expression (its evaluation) has some side effect(s).



            For example:



            int x = y++; //where y is also an int


            In addition to the initialization operation the value of y gets changed due to the side effect of ++ operator.



            So far so good. Moving on to sequence points. An alternation definition of seq-points given by the comp.lang.c author Steve Summit:




            Sequence point is a point in time at which the dust has settled and all side effects which have been seen so far are guaranteed to be complete.






            What are the common sequence points listed in the C++ Standard ?



            Those are:




            • at the end of the evaluation of full expression (§1.9/16) (A full-expression is an expression that is not a subexpression of another expression.)1


            Example :



            int a = 5; // ; is a sequence point here




            • in the evaluation of each of the following expressions after the evaluation of the first expression(§1.9/18) 2





              • a && b (§5.14)

              • a || b (§5.15)

              • a ? b : c (§5.16)


              • a , b (§5.18) (here a , b is a comma operator; in func(a,a++) , is not a comma operator, it's merely a separator between the arguments a and a++. Thus the behaviour is undefined in that case (if a is considered to be a primitive type))




            • at a function call (whether or not the function is inline), after the evaluation of all function arguments (if any) which
              takes place before execution of any expressions or statements in the function body (§1.9/17).



            1 : Note : the evaluation of a full-expression can include the evaluation of subexpressions that are not lexically
            part of the full-expression. For example, subexpressions involved in evaluating default argument expressions (8.3.6) are considered to be created in the expression that calls the function, not the expression that defines the default argument



            2 : The operators indicated are the built-in operators, as described in clause 5. When one of these operators is overloaded (clause 13) in a valid context, thus designating a user-defined operator function, the expression designates a function invocation and the operands form an argument list, without an implied sequence point between them.





            What is Undefined Behaviour?



            The Standard defines Undefined Behaviour in Section §1.3.12 as




            behaviour, such as might arise upon use of an erroneous program construct or erroneous data, for which this International Standard imposes no requirements 3.



            Undefined behaviour may also be expected when this
            International Standard omits the description of any explicit definition of behavior.




            3 : permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or with-
            out the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).



            In short, undefined behaviour means anything can happen from daemons flying out of your nose to your girlfriend getting pregnant.





            What is the relation between Undefined Behaviour and Sequence Points?



            Before I get into that you must know the difference(s) between Undefined Behaviour, Unspecified Behaviour and Implementation Defined Behaviour.



            You must also know that the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified.



            For example:



            int x = 5, y = 6;

            int z = x++ + y++; //it is unspecified whether x++ or y++ will be evaluated first.


            Another example here.





            Now the Standard in §5/4 says




            • 1) 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.


            What does it mean?



            Informally it means that between two sequence points a variable must not be modified more than once.
            In an expression statement, the next sequence point is usually at the terminating semicolon, and the previous sequence point is at the end of the previous statement. An expression may also contain intermediate sequence points.



            From the above sentence the following expressions invoke Undefined Behaviour:



            i++ * ++i;   // UB, i is modified more than once btw two SPs
            i = ++i; // UB, same as above
            ++i = 2; // UB, same as above
            i = ++i + 1; // UB, same as above
            ++++++i; // UB, parsed as (++(++(++i)))

            i = (i, ++i, ++i); // UB, there's no SP between `++i` (right most) and assignment to `i` (`i` is modified more than once btw two SPs)


            But the following expressions are fine:



            i = (i, ++i, 1) + 1; // well defined (AFAIK)
            i = (++i, i++, i); // well defined
            int j = i;
            j = (++i, i++, j*i); // well defined





            • 2) Furthermore, the prior value shall be accessed only to determine the value to be stored.


            What does it mean? It means if an object is written to within a full expression, any and all accesses to it within the same expression must be directly involved in the computation of the value to be written.



            For example in i = i + 1 all the access of i (in L.H.S and in R.H.S) are directly involved in computation of the value to be written. So it is fine.



            This rule effectively constrains legal expressions to those in which the accesses demonstrably precede the modification.



            Example 1:



            std::printf("%d %d", i,++i); // invokes Undefined Behaviour because of Rule no 2


            Example 2:



            a[i] = i++ // or a[++i] = i or a[i++] = ++i etc


            is disallowed because one of the accesses of i (the one in a[i]) has nothing to do with the value which ends up being stored in i (which happens over in i++), and so there's no good way to define--either for our understanding or the compiler's--whether the access should take place before or after the incremented value is stored. So the behaviour is undefined.



            Example 3 :



            int x = i + i++ ;// Similar to above




            Follow up answer for C++11 here.






            share|improve this answer





















            • 45





              *p++ = 4 isn't Undefined Behaviour . *p++ is interpreted as *(p++). p++ returns p(a copy) and the value in stored at the previous address. Why would that invoke UB? It is perfectly fine.

              – Prasoon Saurav
              Nov 14 '10 at 6:23








            • 6





              @Mike: AFAIK, there are no (legal) copies of the C++ Standard you could link to.

              – sbi
              Nov 14 '10 at 9:19






            • 10





              Well, then you could have a link to the ISO's relevant order page. Anyway, thinking about it, the phrase "elementary knowledge of C++ Standard" seems a bit of a contradiction in terms, since if you're reading the standard, you're past the elementary level. Maybe we could list what things in the language you need a basic understanding of, like expression syntax, order of operations, and maybe operator overloading?

              – Mike DeSimone
              Nov 14 '10 at 16:00






            • 37





              I'm not sure quoting the standard is the best way to teach newbies

              – Inverse
              Nov 14 '10 at 18:28






            • 6





              @Adrian The first expression invokes an UB because there is no sequence point between the last ++i and the assignement to i. The second expression does not invoke UB because expression i does not change the value of i. In the second example the i++ is followed by a sequence point (,) before the assignment operator is called.

              – Kolyunya
              Jul 1 '13 at 7:09
















            645












            645








            645







            C++98 and C++03



            This answer is for the older versions of the C++ standard. The C++11 and C++14 versions of the standard do not formally contain 'sequence points'; operations are 'sequenced before' or 'unsequenced' or 'indeterminately sequenced' instead. The net effect is essentially the same, but the terminology is different.





            Disclaimer : Okay. This answer is a bit long. So have patience while reading it. If you already know these things, reading them again won't make you crazy.



            Pre-requisites : An elementary knowledge of C++ Standard





            What are Sequence Points?



            The Standard says




            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. (§1.9/7)




            Side effects? What are side effects?



            Evaluation of an expression produces something and if in addition there is a change in the state of the execution environment it is said that the expression (its evaluation) has some side effect(s).



            For example:



            int x = y++; //where y is also an int


            In addition to the initialization operation the value of y gets changed due to the side effect of ++ operator.



            So far so good. Moving on to sequence points. An alternation definition of seq-points given by the comp.lang.c author Steve Summit:




            Sequence point is a point in time at which the dust has settled and all side effects which have been seen so far are guaranteed to be complete.






            What are the common sequence points listed in the C++ Standard ?



            Those are:




            • at the end of the evaluation of full expression (§1.9/16) (A full-expression is an expression that is not a subexpression of another expression.)1


            Example :



            int a = 5; // ; is a sequence point here




            • in the evaluation of each of the following expressions after the evaluation of the first expression(§1.9/18) 2





              • a && b (§5.14)

              • a || b (§5.15)

              • a ? b : c (§5.16)


              • a , b (§5.18) (here a , b is a comma operator; in func(a,a++) , is not a comma operator, it's merely a separator between the arguments a and a++. Thus the behaviour is undefined in that case (if a is considered to be a primitive type))




            • at a function call (whether or not the function is inline), after the evaluation of all function arguments (if any) which
              takes place before execution of any expressions or statements in the function body (§1.9/17).



            1 : Note : the evaluation of a full-expression can include the evaluation of subexpressions that are not lexically
            part of the full-expression. For example, subexpressions involved in evaluating default argument expressions (8.3.6) are considered to be created in the expression that calls the function, not the expression that defines the default argument



            2 : The operators indicated are the built-in operators, as described in clause 5. When one of these operators is overloaded (clause 13) in a valid context, thus designating a user-defined operator function, the expression designates a function invocation and the operands form an argument list, without an implied sequence point between them.





            What is Undefined Behaviour?



            The Standard defines Undefined Behaviour in Section §1.3.12 as




            behaviour, such as might arise upon use of an erroneous program construct or erroneous data, for which this International Standard imposes no requirements 3.



            Undefined behaviour may also be expected when this
            International Standard omits the description of any explicit definition of behavior.




            3 : permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or with-
            out the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).



            In short, undefined behaviour means anything can happen from daemons flying out of your nose to your girlfriend getting pregnant.





            What is the relation between Undefined Behaviour and Sequence Points?



            Before I get into that you must know the difference(s) between Undefined Behaviour, Unspecified Behaviour and Implementation Defined Behaviour.



            You must also know that the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified.



            For example:



            int x = 5, y = 6;

            int z = x++ + y++; //it is unspecified whether x++ or y++ will be evaluated first.


            Another example here.





            Now the Standard in §5/4 says




            • 1) 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.


            What does it mean?



            Informally it means that between two sequence points a variable must not be modified more than once.
            In an expression statement, the next sequence point is usually at the terminating semicolon, and the previous sequence point is at the end of the previous statement. An expression may also contain intermediate sequence points.



            From the above sentence the following expressions invoke Undefined Behaviour:



            i++ * ++i;   // UB, i is modified more than once btw two SPs
            i = ++i; // UB, same as above
            ++i = 2; // UB, same as above
            i = ++i + 1; // UB, same as above
            ++++++i; // UB, parsed as (++(++(++i)))

            i = (i, ++i, ++i); // UB, there's no SP between `++i` (right most) and assignment to `i` (`i` is modified more than once btw two SPs)


            But the following expressions are fine:



            i = (i, ++i, 1) + 1; // well defined (AFAIK)
            i = (++i, i++, i); // well defined
            int j = i;
            j = (++i, i++, j*i); // well defined





            • 2) Furthermore, the prior value shall be accessed only to determine the value to be stored.


            What does it mean? It means if an object is written to within a full expression, any and all accesses to it within the same expression must be directly involved in the computation of the value to be written.



            For example in i = i + 1 all the access of i (in L.H.S and in R.H.S) are directly involved in computation of the value to be written. So it is fine.



            This rule effectively constrains legal expressions to those in which the accesses demonstrably precede the modification.



            Example 1:



            std::printf("%d %d", i,++i); // invokes Undefined Behaviour because of Rule no 2


            Example 2:



            a[i] = i++ // or a[++i] = i or a[i++] = ++i etc


            is disallowed because one of the accesses of i (the one in a[i]) has nothing to do with the value which ends up being stored in i (which happens over in i++), and so there's no good way to define--either for our understanding or the compiler's--whether the access should take place before or after the incremented value is stored. So the behaviour is undefined.



            Example 3 :



            int x = i + i++ ;// Similar to above




            Follow up answer for C++11 here.






            share|improve this answer















            C++98 and C++03



            This answer is for the older versions of the C++ standard. The C++11 and C++14 versions of the standard do not formally contain 'sequence points'; operations are 'sequenced before' or 'unsequenced' or 'indeterminately sequenced' instead. The net effect is essentially the same, but the terminology is different.





            Disclaimer : Okay. This answer is a bit long. So have patience while reading it. If you already know these things, reading them again won't make you crazy.



            Pre-requisites : An elementary knowledge of C++ Standard





            What are Sequence Points?



            The Standard says




            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. (§1.9/7)




            Side effects? What are side effects?



            Evaluation of an expression produces something and if in addition there is a change in the state of the execution environment it is said that the expression (its evaluation) has some side effect(s).



            For example:



            int x = y++; //where y is also an int


            In addition to the initialization operation the value of y gets changed due to the side effect of ++ operator.



            So far so good. Moving on to sequence points. An alternation definition of seq-points given by the comp.lang.c author Steve Summit:




            Sequence point is a point in time at which the dust has settled and all side effects which have been seen so far are guaranteed to be complete.






            What are the common sequence points listed in the C++ Standard ?



            Those are:




            • at the end of the evaluation of full expression (§1.9/16) (A full-expression is an expression that is not a subexpression of another expression.)1


            Example :



            int a = 5; // ; is a sequence point here




            • in the evaluation of each of the following expressions after the evaluation of the first expression(§1.9/18) 2





              • a && b (§5.14)

              • a || b (§5.15)

              • a ? b : c (§5.16)


              • a , b (§5.18) (here a , b is a comma operator; in func(a,a++) , is not a comma operator, it's merely a separator between the arguments a and a++. Thus the behaviour is undefined in that case (if a is considered to be a primitive type))




            • at a function call (whether or not the function is inline), after the evaluation of all function arguments (if any) which
              takes place before execution of any expressions or statements in the function body (§1.9/17).



            1 : Note : the evaluation of a full-expression can include the evaluation of subexpressions that are not lexically
            part of the full-expression. For example, subexpressions involved in evaluating default argument expressions (8.3.6) are considered to be created in the expression that calls the function, not the expression that defines the default argument



            2 : The operators indicated are the built-in operators, as described in clause 5. When one of these operators is overloaded (clause 13) in a valid context, thus designating a user-defined operator function, the expression designates a function invocation and the operands form an argument list, without an implied sequence point between them.





            What is Undefined Behaviour?



            The Standard defines Undefined Behaviour in Section §1.3.12 as




            behaviour, such as might arise upon use of an erroneous program construct or erroneous data, for which this International Standard imposes no requirements 3.



            Undefined behaviour may also be expected when this
            International Standard omits the description of any explicit definition of behavior.




            3 : permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or with-
            out the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).



            In short, undefined behaviour means anything can happen from daemons flying out of your nose to your girlfriend getting pregnant.





            What is the relation between Undefined Behaviour and Sequence Points?



            Before I get into that you must know the difference(s) between Undefined Behaviour, Unspecified Behaviour and Implementation Defined Behaviour.



            You must also know that the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified.



            For example:



            int x = 5, y = 6;

            int z = x++ + y++; //it is unspecified whether x++ or y++ will be evaluated first.


            Another example here.





            Now the Standard in §5/4 says




            • 1) 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.


            What does it mean?



            Informally it means that between two sequence points a variable must not be modified more than once.
            In an expression statement, the next sequence point is usually at the terminating semicolon, and the previous sequence point is at the end of the previous statement. An expression may also contain intermediate sequence points.



            From the above sentence the following expressions invoke Undefined Behaviour:



            i++ * ++i;   // UB, i is modified more than once btw two SPs
            i = ++i; // UB, same as above
            ++i = 2; // UB, same as above
            i = ++i + 1; // UB, same as above
            ++++++i; // UB, parsed as (++(++(++i)))

            i = (i, ++i, ++i); // UB, there's no SP between `++i` (right most) and assignment to `i` (`i` is modified more than once btw two SPs)


            But the following expressions are fine:



            i = (i, ++i, 1) + 1; // well defined (AFAIK)
            i = (++i, i++, i); // well defined
            int j = i;
            j = (++i, i++, j*i); // well defined





            • 2) Furthermore, the prior value shall be accessed only to determine the value to be stored.


            What does it mean? It means if an object is written to within a full expression, any and all accesses to it within the same expression must be directly involved in the computation of the value to be written.



            For example in i = i + 1 all the access of i (in L.H.S and in R.H.S) are directly involved in computation of the value to be written. So it is fine.



            This rule effectively constrains legal expressions to those in which the accesses demonstrably precede the modification.



            Example 1:



            std::printf("%d %d", i,++i); // invokes Undefined Behaviour because of Rule no 2


            Example 2:



            a[i] = i++ // or a[++i] = i or a[i++] = ++i etc


            is disallowed because one of the accesses of i (the one in a[i]) has nothing to do with the value which ends up being stored in i (which happens over in i++), and so there's no good way to define--either for our understanding or the compiler's--whether the access should take place before or after the incremented value is stored. So the behaviour is undefined.



            Example 3 :



            int x = i + i++ ;// Similar to above




            Follow up answer for C++11 here.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Sep 6 '18 at 5:37


























            community wiki





            26 revs, 13 users 94%
            Prasoon Saurav









            • 45





              *p++ = 4 isn't Undefined Behaviour . *p++ is interpreted as *(p++). p++ returns p(a copy) and the value in stored at the previous address. Why would that invoke UB? It is perfectly fine.

              – Prasoon Saurav
              Nov 14 '10 at 6:23








            • 6





              @Mike: AFAIK, there are no (legal) copies of the C++ Standard you could link to.

              – sbi
              Nov 14 '10 at 9:19






            • 10





              Well, then you could have a link to the ISO's relevant order page. Anyway, thinking about it, the phrase "elementary knowledge of C++ Standard" seems a bit of a contradiction in terms, since if you're reading the standard, you're past the elementary level. Maybe we could list what things in the language you need a basic understanding of, like expression syntax, order of operations, and maybe operator overloading?

              – Mike DeSimone
              Nov 14 '10 at 16:00






            • 37





              I'm not sure quoting the standard is the best way to teach newbies

              – Inverse
              Nov 14 '10 at 18:28






            • 6





              @Adrian The first expression invokes an UB because there is no sequence point between the last ++i and the assignement to i. The second expression does not invoke UB because expression i does not change the value of i. In the second example the i++ is followed by a sequence point (,) before the assignment operator is called.

              – Kolyunya
              Jul 1 '13 at 7:09
















            • 45





              *p++ = 4 isn't Undefined Behaviour . *p++ is interpreted as *(p++). p++ returns p(a copy) and the value in stored at the previous address. Why would that invoke UB? It is perfectly fine.

              – Prasoon Saurav
              Nov 14 '10 at 6:23








            • 6





              @Mike: AFAIK, there are no (legal) copies of the C++ Standard you could link to.

              – sbi
              Nov 14 '10 at 9:19






            • 10





              Well, then you could have a link to the ISO's relevant order page. Anyway, thinking about it, the phrase "elementary knowledge of C++ Standard" seems a bit of a contradiction in terms, since if you're reading the standard, you're past the elementary level. Maybe we could list what things in the language you need a basic understanding of, like expression syntax, order of operations, and maybe operator overloading?

              – Mike DeSimone
              Nov 14 '10 at 16:00






            • 37





              I'm not sure quoting the standard is the best way to teach newbies

              – Inverse
              Nov 14 '10 at 18:28






            • 6





              @Adrian The first expression invokes an UB because there is no sequence point between the last ++i and the assignement to i. The second expression does not invoke UB because expression i does not change the value of i. In the second example the i++ is followed by a sequence point (,) before the assignment operator is called.

              – Kolyunya
              Jul 1 '13 at 7:09










            45




            45





            *p++ = 4 isn't Undefined Behaviour . *p++ is interpreted as *(p++). p++ returns p(a copy) and the value in stored at the previous address. Why would that invoke UB? It is perfectly fine.

            – Prasoon Saurav
            Nov 14 '10 at 6:23







            *p++ = 4 isn't Undefined Behaviour . *p++ is interpreted as *(p++). p++ returns p(a copy) and the value in stored at the previous address. Why would that invoke UB? It is perfectly fine.

            – Prasoon Saurav
            Nov 14 '10 at 6:23






            6




            6





            @Mike: AFAIK, there are no (legal) copies of the C++ Standard you could link to.

            – sbi
            Nov 14 '10 at 9:19





            @Mike: AFAIK, there are no (legal) copies of the C++ Standard you could link to.

            – sbi
            Nov 14 '10 at 9:19




            10




            10





            Well, then you could have a link to the ISO's relevant order page. Anyway, thinking about it, the phrase "elementary knowledge of C++ Standard" seems a bit of a contradiction in terms, since if you're reading the standard, you're past the elementary level. Maybe we could list what things in the language you need a basic understanding of, like expression syntax, order of operations, and maybe operator overloading?

            – Mike DeSimone
            Nov 14 '10 at 16:00





            Well, then you could have a link to the ISO's relevant order page. Anyway, thinking about it, the phrase "elementary knowledge of C++ Standard" seems a bit of a contradiction in terms, since if you're reading the standard, you're past the elementary level. Maybe we could list what things in the language you need a basic understanding of, like expression syntax, order of operations, and maybe operator overloading?

            – Mike DeSimone
            Nov 14 '10 at 16:00




            37




            37





            I'm not sure quoting the standard is the best way to teach newbies

            – Inverse
            Nov 14 '10 at 18:28





            I'm not sure quoting the standard is the best way to teach newbies

            – Inverse
            Nov 14 '10 at 18:28




            6




            6





            @Adrian The first expression invokes an UB because there is no sequence point between the last ++i and the assignement to i. The second expression does not invoke UB because expression i does not change the value of i. In the second example the i++ is followed by a sequence point (,) before the assignment operator is called.

            – Kolyunya
            Jul 1 '13 at 7:09







            @Adrian The first expression invokes an UB because there is no sequence point between the last ++i and the assignement to i. The second expression does not invoke UB because expression i does not change the value of i. In the second example the i++ is followed by a sequence point (,) before the assignment operator is called.

            – Kolyunya
            Jul 1 '13 at 7:09















            264














            This is a follow up to my previous answer and contains C++11 related material..





            Pre-requisites : An elementary knowledge of Relations (Mathematics).





            Is it true that there are no Sequence Points in C++11?



            Yes! This is very true.



            Sequence Points have been replaced by Sequenced Before and Sequenced After (and Unsequenced and Indeterminately Sequenced) relations in C++11.





            What exactly is this 'Sequenced before' thing?



            Sequenced Before(§1.9/13) is a relation which is:





            • Asymmetric

            • Transitive


            between evaluations executed by a single thread and induces a strict partial order1



            Formally it means given any two evaluations(See below)A and B, if A is sequenced before B, then the execution of A shall precede the execution of B. If A is not sequenced before B and B is not sequenced before A, then A and B are unsequenced 2.



            Evaluations A and B are indeterminately sequenced when either A is sequenced before B or B is sequenced before A, but it is unspecified which3.



            [NOTES]

            1 : A strict partial order is a binary relation "<" over a set P which is asymmetric, and transitive, i.e., for all a, b, and c in P, we have that:
            ........(i). if a < b then ¬ (b < a) (asymmetry);

            ........(ii). if a < b and b < c then a < c (transitivity).

            2 : The execution of unsequenced evaluations can overlap.

            3 : Indeterminately sequenced evaluations cannot overlap, but either could be executed first.





            What is the meaning of the word 'evaluation' in context of C++11?



            In C++11, evaluation of an expression (or a sub-expression) in general includes:




            • value computations (including determining the identity of an object for glvalue evaluation and fetching a value previously assigned to an object for prvalue evaluation) and


            • initiation of side effects.



            Now (§1.9/14) says:




            Every value computation and side effect associated with a full-expression is sequenced before every value computation and side effect associated with the next full-expression to be evaluated.






            • Trivial example:



              int x;
              x = 10;
              ++x;



              Value computation and side effect associated with ++x is sequenced after the value computation and side effect of x = 10;






            So there must be some relation between Undefined Behaviour and the above-mentioned things, right?



            Yes! Right.



            In (§1.9/15) it has been mentioned that




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




            For example :



            int main()
            {
            int num = 19 ;
            num = (num << 3) + (num >> 3);
            }



            1. Evaluation of operands of + operator are unsequenced relative to each other.

            2. Evaluation of operands of << and >> operators are unsequenced relative to each other.


            4: In an expression that is evaluated more than once during the execution
            of a program, unsequenced and indeterminately sequenced evaluations of its subexpressions need not be performed consistently in different evaluations.




            (§1.9/15)
            The value computations of the operands of an
            operator are sequenced before the value computation of the result of the operator.




            That means in x + y the value computation of x and y are sequenced before the value computation of (x + y).



            More importantly




            (§1.9/15) If a side effect on a scalar object is unsequenced relative to either



            (a) another side effect on the same scalar object



            or



            (b) a value computation using the value of the same scalar object.



            the behaviour is undefined.




            Examples:



            int i = 5, v[10] = { };
            void f(int, int);



            1. i = i++ * ++i; // Undefined Behaviour


            2. i = ++i + i++; // Undefined Behaviour

            3. i = ++i + ++i; // Undefined Behaviour

            4. i = v[i++]; // Undefined Behaviour

            5. i = v[++i]: // Well-defined Behavior

            6. i = i++ + 1; // Undefined Behaviour

            7. i = ++i + 1; // Well-defined Behaviour

            8. ++++i; // Well-defined Behaviour

            9. f(i = -1, i = -1); // Undefined Behaviour (see below)



            When calling a function (whether or not the function is inline), every value computation and side effect associated with any argument expression, or with the postfix expression designating the called function, is sequenced before execution of every expression or statement in the body of the called function. [Note: Value computations and side effects associated with different argument expressions are unsequenced. — end note]




            Expressions (5), (7) and (8) do not invoke undefined behaviour. Check out the following answers for a more detailed explanation.




            • Multiple preincrement operations on a variable in C++0x

            • Unsequenced Value Computations




            Final Note :



            If you find any flaw in the post please leave a comment. Power-users (With rep >20000) please do not hesitate to edit the post for correcting typos and other mistakes.






            share|improve this answer





















            • 3





              Instead of "asymmetric", sequenced before / after are "antisymmetric" relations. This should be changed in the text to conform to the definition of a partial order given later (which also agrees with Wikipedia).

              – TemplateRex
              Jul 21 '12 at 21:47






            • 1





              Why is 7) item in the last example an UB? Maybe it should be f(i = -1, i = 1)?

              – Mikhail
              Mar 18 '14 at 12:04






            • 1





              Here is the nice explanation: stackoverflow.com/a/21671069

              – Mikhail
              Mar 18 '14 at 12:16






            • 1





              I fixed the description of the "sequenced before" relation. It is a strict partial order. Obviously, an expression cannot be sequenced before itself, so the relation cannot be reflexive. Hence it is asymmetric not anti-symmetric.

              – ThomasMcLeod
              Jun 24 '14 at 20:52








            • 1





              5) being well befined blew my mind off. the explanation by Johannes Schaub wasn't entirely straightforward to get. Especially because I believed that even in ++i (being value evaluated before the + operator that is using it), the standard still doesn't say that its side effect must be finished. But in fact, because it returns an ref to a lvalue which is i itself, it MUST have finished the side effect since the evaluation must be finished, therefore the value must be up to date. This was the crazy part to get in fact.

              – v.oddou
              Jan 9 '15 at 6:31


















            264














            This is a follow up to my previous answer and contains C++11 related material..





            Pre-requisites : An elementary knowledge of Relations (Mathematics).





            Is it true that there are no Sequence Points in C++11?



            Yes! This is very true.



            Sequence Points have been replaced by Sequenced Before and Sequenced After (and Unsequenced and Indeterminately Sequenced) relations in C++11.





            What exactly is this 'Sequenced before' thing?



            Sequenced Before(§1.9/13) is a relation which is:





            • Asymmetric

            • Transitive


            between evaluations executed by a single thread and induces a strict partial order1



            Formally it means given any two evaluations(See below)A and B, if A is sequenced before B, then the execution of A shall precede the execution of B. If A is not sequenced before B and B is not sequenced before A, then A and B are unsequenced 2.



            Evaluations A and B are indeterminately sequenced when either A is sequenced before B or B is sequenced before A, but it is unspecified which3.



            [NOTES]

            1 : A strict partial order is a binary relation "<" over a set P which is asymmetric, and transitive, i.e., for all a, b, and c in P, we have that:
            ........(i). if a < b then ¬ (b < a) (asymmetry);

            ........(ii). if a < b and b < c then a < c (transitivity).

            2 : The execution of unsequenced evaluations can overlap.

            3 : Indeterminately sequenced evaluations cannot overlap, but either could be executed first.





            What is the meaning of the word 'evaluation' in context of C++11?



            In C++11, evaluation of an expression (or a sub-expression) in general includes:




            • value computations (including determining the identity of an object for glvalue evaluation and fetching a value previously assigned to an object for prvalue evaluation) and


            • initiation of side effects.



            Now (§1.9/14) says:




            Every value computation and side effect associated with a full-expression is sequenced before every value computation and side effect associated with the next full-expression to be evaluated.






            • Trivial example:



              int x;
              x = 10;
              ++x;



              Value computation and side effect associated with ++x is sequenced after the value computation and side effect of x = 10;






            So there must be some relation between Undefined Behaviour and the above-mentioned things, right?



            Yes! Right.



            In (§1.9/15) it has been mentioned that




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




            For example :



            int main()
            {
            int num = 19 ;
            num = (num << 3) + (num >> 3);
            }



            1. Evaluation of operands of + operator are unsequenced relative to each other.

            2. Evaluation of operands of << and >> operators are unsequenced relative to each other.


            4: In an expression that is evaluated more than once during the execution
            of a program, unsequenced and indeterminately sequenced evaluations of its subexpressions need not be performed consistently in different evaluations.




            (§1.9/15)
            The value computations of the operands of an
            operator are sequenced before the value computation of the result of the operator.




            That means in x + y the value computation of x and y are sequenced before the value computation of (x + y).



            More importantly




            (§1.9/15) If a side effect on a scalar object is unsequenced relative to either



            (a) another side effect on the same scalar object



            or



            (b) a value computation using the value of the same scalar object.



            the behaviour is undefined.




            Examples:



            int i = 5, v[10] = { };
            void f(int, int);



            1. i = i++ * ++i; // Undefined Behaviour


            2. i = ++i + i++; // Undefined Behaviour

            3. i = ++i + ++i; // Undefined Behaviour

            4. i = v[i++]; // Undefined Behaviour

            5. i = v[++i]: // Well-defined Behavior

            6. i = i++ + 1; // Undefined Behaviour

            7. i = ++i + 1; // Well-defined Behaviour

            8. ++++i; // Well-defined Behaviour

            9. f(i = -1, i = -1); // Undefined Behaviour (see below)



            When calling a function (whether or not the function is inline), every value computation and side effect associated with any argument expression, or with the postfix expression designating the called function, is sequenced before execution of every expression or statement in the body of the called function. [Note: Value computations and side effects associated with different argument expressions are unsequenced. — end note]




            Expressions (5), (7) and (8) do not invoke undefined behaviour. Check out the following answers for a more detailed explanation.




            • Multiple preincrement operations on a variable in C++0x

            • Unsequenced Value Computations




            Final Note :



            If you find any flaw in the post please leave a comment. Power-users (With rep >20000) please do not hesitate to edit the post for correcting typos and other mistakes.






            share|improve this answer





















            • 3





              Instead of "asymmetric", sequenced before / after are "antisymmetric" relations. This should be changed in the text to conform to the definition of a partial order given later (which also agrees with Wikipedia).

              – TemplateRex
              Jul 21 '12 at 21:47






            • 1





              Why is 7) item in the last example an UB? Maybe it should be f(i = -1, i = 1)?

              – Mikhail
              Mar 18 '14 at 12:04






            • 1





              Here is the nice explanation: stackoverflow.com/a/21671069

              – Mikhail
              Mar 18 '14 at 12:16






            • 1





              I fixed the description of the "sequenced before" relation. It is a strict partial order. Obviously, an expression cannot be sequenced before itself, so the relation cannot be reflexive. Hence it is asymmetric not anti-symmetric.

              – ThomasMcLeod
              Jun 24 '14 at 20:52








            • 1





              5) being well befined blew my mind off. the explanation by Johannes Schaub wasn't entirely straightforward to get. Especially because I believed that even in ++i (being value evaluated before the + operator that is using it), the standard still doesn't say that its side effect must be finished. But in fact, because it returns an ref to a lvalue which is i itself, it MUST have finished the side effect since the evaluation must be finished, therefore the value must be up to date. This was the crazy part to get in fact.

              – v.oddou
              Jan 9 '15 at 6:31
















            264












            264








            264







            This is a follow up to my previous answer and contains C++11 related material..





            Pre-requisites : An elementary knowledge of Relations (Mathematics).





            Is it true that there are no Sequence Points in C++11?



            Yes! This is very true.



            Sequence Points have been replaced by Sequenced Before and Sequenced After (and Unsequenced and Indeterminately Sequenced) relations in C++11.





            What exactly is this 'Sequenced before' thing?



            Sequenced Before(§1.9/13) is a relation which is:





            • Asymmetric

            • Transitive


            between evaluations executed by a single thread and induces a strict partial order1



            Formally it means given any two evaluations(See below)A and B, if A is sequenced before B, then the execution of A shall precede the execution of B. If A is not sequenced before B and B is not sequenced before A, then A and B are unsequenced 2.



            Evaluations A and B are indeterminately sequenced when either A is sequenced before B or B is sequenced before A, but it is unspecified which3.



            [NOTES]

            1 : A strict partial order is a binary relation "<" over a set P which is asymmetric, and transitive, i.e., for all a, b, and c in P, we have that:
            ........(i). if a < b then ¬ (b < a) (asymmetry);

            ........(ii). if a < b and b < c then a < c (transitivity).

            2 : The execution of unsequenced evaluations can overlap.

            3 : Indeterminately sequenced evaluations cannot overlap, but either could be executed first.





            What is the meaning of the word 'evaluation' in context of C++11?



            In C++11, evaluation of an expression (or a sub-expression) in general includes:




            • value computations (including determining the identity of an object for glvalue evaluation and fetching a value previously assigned to an object for prvalue evaluation) and


            • initiation of side effects.



            Now (§1.9/14) says:




            Every value computation and side effect associated with a full-expression is sequenced before every value computation and side effect associated with the next full-expression to be evaluated.






            • Trivial example:



              int x;
              x = 10;
              ++x;



              Value computation and side effect associated with ++x is sequenced after the value computation and side effect of x = 10;






            So there must be some relation between Undefined Behaviour and the above-mentioned things, right?



            Yes! Right.



            In (§1.9/15) it has been mentioned that




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




            For example :



            int main()
            {
            int num = 19 ;
            num = (num << 3) + (num >> 3);
            }



            1. Evaluation of operands of + operator are unsequenced relative to each other.

            2. Evaluation of operands of << and >> operators are unsequenced relative to each other.


            4: In an expression that is evaluated more than once during the execution
            of a program, unsequenced and indeterminately sequenced evaluations of its subexpressions need not be performed consistently in different evaluations.




            (§1.9/15)
            The value computations of the operands of an
            operator are sequenced before the value computation of the result of the operator.




            That means in x + y the value computation of x and y are sequenced before the value computation of (x + y).



            More importantly




            (§1.9/15) If a side effect on a scalar object is unsequenced relative to either



            (a) another side effect on the same scalar object



            or



            (b) a value computation using the value of the same scalar object.



            the behaviour is undefined.




            Examples:



            int i = 5, v[10] = { };
            void f(int, int);



            1. i = i++ * ++i; // Undefined Behaviour


            2. i = ++i + i++; // Undefined Behaviour

            3. i = ++i + ++i; // Undefined Behaviour

            4. i = v[i++]; // Undefined Behaviour

            5. i = v[++i]: // Well-defined Behavior

            6. i = i++ + 1; // Undefined Behaviour

            7. i = ++i + 1; // Well-defined Behaviour

            8. ++++i; // Well-defined Behaviour

            9. f(i = -1, i = -1); // Undefined Behaviour (see below)



            When calling a function (whether or not the function is inline), every value computation and side effect associated with any argument expression, or with the postfix expression designating the called function, is sequenced before execution of every expression or statement in the body of the called function. [Note: Value computations and side effects associated with different argument expressions are unsequenced. — end note]




            Expressions (5), (7) and (8) do not invoke undefined behaviour. Check out the following answers for a more detailed explanation.




            • Multiple preincrement operations on a variable in C++0x

            • Unsequenced Value Computations




            Final Note :



            If you find any flaw in the post please leave a comment. Power-users (With rep >20000) please do not hesitate to edit the post for correcting typos and other mistakes.






            share|improve this answer















            This is a follow up to my previous answer and contains C++11 related material..





            Pre-requisites : An elementary knowledge of Relations (Mathematics).





            Is it true that there are no Sequence Points in C++11?



            Yes! This is very true.



            Sequence Points have been replaced by Sequenced Before and Sequenced After (and Unsequenced and Indeterminately Sequenced) relations in C++11.





            What exactly is this 'Sequenced before' thing?



            Sequenced Before(§1.9/13) is a relation which is:





            • Asymmetric

            • Transitive


            between evaluations executed by a single thread and induces a strict partial order1



            Formally it means given any two evaluations(See below)A and B, if A is sequenced before B, then the execution of A shall precede the execution of B. If A is not sequenced before B and B is not sequenced before A, then A and B are unsequenced 2.



            Evaluations A and B are indeterminately sequenced when either A is sequenced before B or B is sequenced before A, but it is unspecified which3.



            [NOTES]

            1 : A strict partial order is a binary relation "<" over a set P which is asymmetric, and transitive, i.e., for all a, b, and c in P, we have that:
            ........(i). if a < b then ¬ (b < a) (asymmetry);

            ........(ii). if a < b and b < c then a < c (transitivity).

            2 : The execution of unsequenced evaluations can overlap.

            3 : Indeterminately sequenced evaluations cannot overlap, but either could be executed first.





            What is the meaning of the word 'evaluation' in context of C++11?



            In C++11, evaluation of an expression (or a sub-expression) in general includes:




            • value computations (including determining the identity of an object for glvalue evaluation and fetching a value previously assigned to an object for prvalue evaluation) and


            • initiation of side effects.



            Now (§1.9/14) says:




            Every value computation and side effect associated with a full-expression is sequenced before every value computation and side effect associated with the next full-expression to be evaluated.






            • Trivial example:



              int x;
              x = 10;
              ++x;



              Value computation and side effect associated with ++x is sequenced after the value computation and side effect of x = 10;






            So there must be some relation between Undefined Behaviour and the above-mentioned things, right?



            Yes! Right.



            In (§1.9/15) it has been mentioned that




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




            For example :



            int main()
            {
            int num = 19 ;
            num = (num << 3) + (num >> 3);
            }



            1. Evaluation of operands of + operator are unsequenced relative to each other.

            2. Evaluation of operands of << and >> operators are unsequenced relative to each other.


            4: In an expression that is evaluated more than once during the execution
            of a program, unsequenced and indeterminately sequenced evaluations of its subexpressions need not be performed consistently in different evaluations.




            (§1.9/15)
            The value computations of the operands of an
            operator are sequenced before the value computation of the result of the operator.




            That means in x + y the value computation of x and y are sequenced before the value computation of (x + y).



            More importantly




            (§1.9/15) If a side effect on a scalar object is unsequenced relative to either



            (a) another side effect on the same scalar object



            or



            (b) a value computation using the value of the same scalar object.



            the behaviour is undefined.




            Examples:



            int i = 5, v[10] = { };
            void f(int, int);



            1. i = i++ * ++i; // Undefined Behaviour


            2. i = ++i + i++; // Undefined Behaviour

            3. i = ++i + ++i; // Undefined Behaviour

            4. i = v[i++]; // Undefined Behaviour

            5. i = v[++i]: // Well-defined Behavior

            6. i = i++ + 1; // Undefined Behaviour

            7. i = ++i + 1; // Well-defined Behaviour

            8. ++++i; // Well-defined Behaviour

            9. f(i = -1, i = -1); // Undefined Behaviour (see below)



            When calling a function (whether or not the function is inline), every value computation and side effect associated with any argument expression, or with the postfix expression designating the called function, is sequenced before execution of every expression or statement in the body of the called function. [Note: Value computations and side effects associated with different argument expressions are unsequenced. — end note]




            Expressions (5), (7) and (8) do not invoke undefined behaviour. Check out the following answers for a more detailed explanation.




            • Multiple preincrement operations on a variable in C++0x

            • Unsequenced Value Computations




            Final Note :



            If you find any flaw in the post please leave a comment. Power-users (With rep >20000) please do not hesitate to edit the post for correcting typos and other mistakes.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited May 23 '17 at 12:10


























            community wiki





            16 revs, 13 users 77%
            Prasoon Saurav









            • 3





              Instead of "asymmetric", sequenced before / after are "antisymmetric" relations. This should be changed in the text to conform to the definition of a partial order given later (which also agrees with Wikipedia).

              – TemplateRex
              Jul 21 '12 at 21:47






            • 1





              Why is 7) item in the last example an UB? Maybe it should be f(i = -1, i = 1)?

              – Mikhail
              Mar 18 '14 at 12:04






            • 1





              Here is the nice explanation: stackoverflow.com/a/21671069

              – Mikhail
              Mar 18 '14 at 12:16






            • 1





              I fixed the description of the "sequenced before" relation. It is a strict partial order. Obviously, an expression cannot be sequenced before itself, so the relation cannot be reflexive. Hence it is asymmetric not anti-symmetric.

              – ThomasMcLeod
              Jun 24 '14 at 20:52








            • 1





              5) being well befined blew my mind off. the explanation by Johannes Schaub wasn't entirely straightforward to get. Especially because I believed that even in ++i (being value evaluated before the + operator that is using it), the standard still doesn't say that its side effect must be finished. But in fact, because it returns an ref to a lvalue which is i itself, it MUST have finished the side effect since the evaluation must be finished, therefore the value must be up to date. This was the crazy part to get in fact.

              – v.oddou
              Jan 9 '15 at 6:31
















            • 3





              Instead of "asymmetric", sequenced before / after are "antisymmetric" relations. This should be changed in the text to conform to the definition of a partial order given later (which also agrees with Wikipedia).

              – TemplateRex
              Jul 21 '12 at 21:47






            • 1





              Why is 7) item in the last example an UB? Maybe it should be f(i = -1, i = 1)?

              – Mikhail
              Mar 18 '14 at 12:04






            • 1





              Here is the nice explanation: stackoverflow.com/a/21671069

              – Mikhail
              Mar 18 '14 at 12:16






            • 1





              I fixed the description of the "sequenced before" relation. It is a strict partial order. Obviously, an expression cannot be sequenced before itself, so the relation cannot be reflexive. Hence it is asymmetric not anti-symmetric.

              – ThomasMcLeod
              Jun 24 '14 at 20:52








            • 1





              5) being well befined blew my mind off. the explanation by Johannes Schaub wasn't entirely straightforward to get. Especially because I believed that even in ++i (being value evaluated before the + operator that is using it), the standard still doesn't say that its side effect must be finished. But in fact, because it returns an ref to a lvalue which is i itself, it MUST have finished the side effect since the evaluation must be finished, therefore the value must be up to date. This was the crazy part to get in fact.

              – v.oddou
              Jan 9 '15 at 6:31










            3




            3





            Instead of "asymmetric", sequenced before / after are "antisymmetric" relations. This should be changed in the text to conform to the definition of a partial order given later (which also agrees with Wikipedia).

            – TemplateRex
            Jul 21 '12 at 21:47





            Instead of "asymmetric", sequenced before / after are "antisymmetric" relations. This should be changed in the text to conform to the definition of a partial order given later (which also agrees with Wikipedia).

            – TemplateRex
            Jul 21 '12 at 21:47




            1




            1





            Why is 7) item in the last example an UB? Maybe it should be f(i = -1, i = 1)?

            – Mikhail
            Mar 18 '14 at 12:04





            Why is 7) item in the last example an UB? Maybe it should be f(i = -1, i = 1)?

            – Mikhail
            Mar 18 '14 at 12:04




            1




            1





            Here is the nice explanation: stackoverflow.com/a/21671069

            – Mikhail
            Mar 18 '14 at 12:16





            Here is the nice explanation: stackoverflow.com/a/21671069

            – Mikhail
            Mar 18 '14 at 12:16




            1




            1





            I fixed the description of the "sequenced before" relation. It is a strict partial order. Obviously, an expression cannot be sequenced before itself, so the relation cannot be reflexive. Hence it is asymmetric not anti-symmetric.

            – ThomasMcLeod
            Jun 24 '14 at 20:52







            I fixed the description of the "sequenced before" relation. It is a strict partial order. Obviously, an expression cannot be sequenced before itself, so the relation cannot be reflexive. Hence it is asymmetric not anti-symmetric.

            – ThomasMcLeod
            Jun 24 '14 at 20:52






            1




            1





            5) being well befined blew my mind off. the explanation by Johannes Schaub wasn't entirely straightforward to get. Especially because I believed that even in ++i (being value evaluated before the + operator that is using it), the standard still doesn't say that its side effect must be finished. But in fact, because it returns an ref to a lvalue which is i itself, it MUST have finished the side effect since the evaluation must be finished, therefore the value must be up to date. This was the crazy part to get in fact.

            – v.oddou
            Jan 9 '15 at 6:31







            5) being well befined blew my mind off. the explanation by Johannes Schaub wasn't entirely straightforward to get. Especially because I believed that even in ++i (being value evaluated before the + operator that is using it), the standard still doesn't say that its side effect must be finished. But in fact, because it returns an ref to a lvalue which is i itself, it MUST have finished the side effect since the evaluation must be finished, therefore the value must be up to date. This was the crazy part to get in fact.

            – v.oddou
            Jan 9 '15 at 6:31













            19














            C++17 (N4659) includes a proposal Refining Expression Evaluation Order for Idiomatic C++
            which defines a stricter order of expression evaluation.



            In particular, the following sentence was added:




            8.18 Assignment and compound assignment operators:
            ....



            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.
            The right operand is sequenced before the left operand.




            It makes several cases of previously undefined behavior valid, including the one in question:



            a[++i] = i;


            However several other similar cases still lead to undefined behavior.



            In N4140:



            i = i++ + 1; // the behavior is undefined


            But in N4659



            i = i++ + 1; // the value of i is incremented
            i = i++ + i; // the behavior is undefined


            Of course, using a C++17 compliant compiler does not necessarily mean that one should start writing such expressions.






            share|improve this answer






























              19














              C++17 (N4659) includes a proposal Refining Expression Evaluation Order for Idiomatic C++
              which defines a stricter order of expression evaluation.



              In particular, the following sentence was added:




              8.18 Assignment and compound assignment operators:
              ....



              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.
              The right operand is sequenced before the left operand.




              It makes several cases of previously undefined behavior valid, including the one in question:



              a[++i] = i;


              However several other similar cases still lead to undefined behavior.



              In N4140:



              i = i++ + 1; // the behavior is undefined


              But in N4659



              i = i++ + 1; // the value of i is incremented
              i = i++ + i; // the behavior is undefined


              Of course, using a C++17 compliant compiler does not necessarily mean that one should start writing such expressions.






              share|improve this answer




























                19












                19








                19







                C++17 (N4659) includes a proposal Refining Expression Evaluation Order for Idiomatic C++
                which defines a stricter order of expression evaluation.



                In particular, the following sentence was added:




                8.18 Assignment and compound assignment operators:
                ....



                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.
                The right operand is sequenced before the left operand.




                It makes several cases of previously undefined behavior valid, including the one in question:



                a[++i] = i;


                However several other similar cases still lead to undefined behavior.



                In N4140:



                i = i++ + 1; // the behavior is undefined


                But in N4659



                i = i++ + 1; // the value of i is incremented
                i = i++ + i; // the behavior is undefined


                Of course, using a C++17 compliant compiler does not necessarily mean that one should start writing such expressions.






                share|improve this answer















                C++17 (N4659) includes a proposal Refining Expression Evaluation Order for Idiomatic C++
                which defines a stricter order of expression evaluation.



                In particular, the following sentence was added:




                8.18 Assignment and compound assignment operators:
                ....



                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.
                The right operand is sequenced before the left operand.




                It makes several cases of previously undefined behavior valid, including the one in question:



                a[++i] = i;


                However several other similar cases still lead to undefined behavior.



                In N4140:



                i = i++ + 1; // the behavior is undefined


                But in N4659



                i = i++ + 1; // the value of i is incremented
                i = i++ + i; // the behavior is undefined


                Of course, using a C++17 compliant compiler does not necessarily mean that one should start writing such expressions.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Sep 12 '17 at 14:58


























                community wiki





                2 revs, 2 users 98%
                AlexD
























                    11














                    I am guessing there is a fundamental reason for the change, it isn't merely cosmetic to make the old interpretation clearer: that reason is concurrency. Unspecified order of elaboration is merely selection of one of several possible serial orderings, this is quite different to before and after orderings, because if there is no specified ordering, concurrent evaluation is possible: not so with the old rules. For example in:



                    f (a,b)


                    previously either a then b, or, b then a. Now, a and b can be evaluated with instructions interleaved or even on different cores.






                    share|improve this answer





















                    • 5





                      I believe, though, that if either 'a' or 'b' includes a function call, they are indeterminately sequenced rather than unsequenced, which is to say that all side-effects from one are required to occur before any side-effects from the other, although the compiler need not be consistent about which one goes first. If that is no longer true, it would break a lot of code which relies upon the operations not overlapping (e.g. if 'a' and 'b' each set up, use, and take down, a shared static state).

                      – supercat
                      Dec 9 '10 at 20:35
















                    11














                    I am guessing there is a fundamental reason for the change, it isn't merely cosmetic to make the old interpretation clearer: that reason is concurrency. Unspecified order of elaboration is merely selection of one of several possible serial orderings, this is quite different to before and after orderings, because if there is no specified ordering, concurrent evaluation is possible: not so with the old rules. For example in:



                    f (a,b)


                    previously either a then b, or, b then a. Now, a and b can be evaluated with instructions interleaved or even on different cores.






                    share|improve this answer





















                    • 5





                      I believe, though, that if either 'a' or 'b' includes a function call, they are indeterminately sequenced rather than unsequenced, which is to say that all side-effects from one are required to occur before any side-effects from the other, although the compiler need not be consistent about which one goes first. If that is no longer true, it would break a lot of code which relies upon the operations not overlapping (e.g. if 'a' and 'b' each set up, use, and take down, a shared static state).

                      – supercat
                      Dec 9 '10 at 20:35














                    11












                    11








                    11







                    I am guessing there is a fundamental reason for the change, it isn't merely cosmetic to make the old interpretation clearer: that reason is concurrency. Unspecified order of elaboration is merely selection of one of several possible serial orderings, this is quite different to before and after orderings, because if there is no specified ordering, concurrent evaluation is possible: not so with the old rules. For example in:



                    f (a,b)


                    previously either a then b, or, b then a. Now, a and b can be evaluated with instructions interleaved or even on different cores.






                    share|improve this answer















                    I am guessing there is a fundamental reason for the change, it isn't merely cosmetic to make the old interpretation clearer: that reason is concurrency. Unspecified order of elaboration is merely selection of one of several possible serial orderings, this is quite different to before and after orderings, because if there is no specified ordering, concurrent evaluation is possible: not so with the old rules. For example in:



                    f (a,b)


                    previously either a then b, or, b then a. Now, a and b can be evaluated with instructions interleaved or even on different cores.







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    answered Dec 7 '10 at 19:44


























                    community wiki





                    Yttrill









                    • 5





                      I believe, though, that if either 'a' or 'b' includes a function call, they are indeterminately sequenced rather than unsequenced, which is to say that all side-effects from one are required to occur before any side-effects from the other, although the compiler need not be consistent about which one goes first. If that is no longer true, it would break a lot of code which relies upon the operations not overlapping (e.g. if 'a' and 'b' each set up, use, and take down, a shared static state).

                      – supercat
                      Dec 9 '10 at 20:35














                    • 5





                      I believe, though, that if either 'a' or 'b' includes a function call, they are indeterminately sequenced rather than unsequenced, which is to say that all side-effects from one are required to occur before any side-effects from the other, although the compiler need not be consistent about which one goes first. If that is no longer true, it would break a lot of code which relies upon the operations not overlapping (e.g. if 'a' and 'b' each set up, use, and take down, a shared static state).

                      – supercat
                      Dec 9 '10 at 20:35








                    5




                    5





                    I believe, though, that if either 'a' or 'b' includes a function call, they are indeterminately sequenced rather than unsequenced, which is to say that all side-effects from one are required to occur before any side-effects from the other, although the compiler need not be consistent about which one goes first. If that is no longer true, it would break a lot of code which relies upon the operations not overlapping (e.g. if 'a' and 'b' each set up, use, and take down, a shared static state).

                    – supercat
                    Dec 9 '10 at 20:35





                    I believe, though, that if either 'a' or 'b' includes a function call, they are indeterminately sequenced rather than unsequenced, which is to say that all side-effects from one are required to occur before any side-effects from the other, although the compiler need not be consistent about which one goes first. If that is no longer true, it would break a lot of code which relies upon the operations not overlapping (e.g. if 'a' and 'b' each set up, use, and take down, a shared static state).

                    – supercat
                    Dec 9 '10 at 20:35











                    0














                    In C99(ISO/IEC 9899:TC3) which seems absent from this discussion thus far the following steteents are made regarding order of evaluaiton.




                    [...]the order of evaluation of subexpressions and the order in which
                    side effects take place are both unspecified. (Section 6.5 pp 67)



                    The order of evaluation of the operands is unspecified. If an attempt
                    is made to modify the result of an assignment operator or to access it
                    after the next sequence point, the behavior[sic] is undefined.(Section
                    6.5.16 pp 91)







                    share|improve this answer





















                    • 1





                      The question is tagged C++ and not C, which is good because the behaviour in C++17 is quite different from the behaviour in older versions — and bears no relation to the behaviour in C11, C99, C90, etc. Or bears very little relation to it. On the whole, I'd suggest removing this. More significantly, we need to find the equivalent Q&A for C and make sure it is OK (and notes that C++17, in particular, changes the rules — the behaviour in C++11 and before was more or less the same as in C11, though the verbiage describing it in C still uses 'sequence points' whereas C++11 and later does not.

                      – Jonathan Leffler
                      Nov 30 '18 at 5:34
















                    0














                    In C99(ISO/IEC 9899:TC3) which seems absent from this discussion thus far the following steteents are made regarding order of evaluaiton.




                    [...]the order of evaluation of subexpressions and the order in which
                    side effects take place are both unspecified. (Section 6.5 pp 67)



                    The order of evaluation of the operands is unspecified. If an attempt
                    is made to modify the result of an assignment operator or to access it
                    after the next sequence point, the behavior[sic] is undefined.(Section
                    6.5.16 pp 91)







                    share|improve this answer





















                    • 1





                      The question is tagged C++ and not C, which is good because the behaviour in C++17 is quite different from the behaviour in older versions — and bears no relation to the behaviour in C11, C99, C90, etc. Or bears very little relation to it. On the whole, I'd suggest removing this. More significantly, we need to find the equivalent Q&A for C and make sure it is OK (and notes that C++17, in particular, changes the rules — the behaviour in C++11 and before was more or less the same as in C11, though the verbiage describing it in C still uses 'sequence points' whereas C++11 and later does not.

                      – Jonathan Leffler
                      Nov 30 '18 at 5:34














                    0












                    0








                    0







                    In C99(ISO/IEC 9899:TC3) which seems absent from this discussion thus far the following steteents are made regarding order of evaluaiton.




                    [...]the order of evaluation of subexpressions and the order in which
                    side effects take place are both unspecified. (Section 6.5 pp 67)



                    The order of evaluation of the operands is unspecified. If an attempt
                    is made to modify the result of an assignment operator or to access it
                    after the next sequence point, the behavior[sic] is undefined.(Section
                    6.5.16 pp 91)







                    share|improve this answer















                    In C99(ISO/IEC 9899:TC3) which seems absent from this discussion thus far the following steteents are made regarding order of evaluaiton.




                    [...]the order of evaluation of subexpressions and the order in which
                    side effects take place are both unspecified. (Section 6.5 pp 67)



                    The order of evaluation of the operands is unspecified. If an attempt
                    is made to modify the result of an assignment operator or to access it
                    after the next sequence point, the behavior[sic] is undefined.(Section
                    6.5.16 pp 91)








                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    answered Oct 26 '18 at 3:40


























                    community wiki





                    awiebe









                    • 1





                      The question is tagged C++ and not C, which is good because the behaviour in C++17 is quite different from the behaviour in older versions — and bears no relation to the behaviour in C11, C99, C90, etc. Or bears very little relation to it. On the whole, I'd suggest removing this. More significantly, we need to find the equivalent Q&A for C and make sure it is OK (and notes that C++17, in particular, changes the rules — the behaviour in C++11 and before was more or less the same as in C11, though the verbiage describing it in C still uses 'sequence points' whereas C++11 and later does not.

                      – Jonathan Leffler
                      Nov 30 '18 at 5:34














                    • 1





                      The question is tagged C++ and not C, which is good because the behaviour in C++17 is quite different from the behaviour in older versions — and bears no relation to the behaviour in C11, C99, C90, etc. Or bears very little relation to it. On the whole, I'd suggest removing this. More significantly, we need to find the equivalent Q&A for C and make sure it is OK (and notes that C++17, in particular, changes the rules — the behaviour in C++11 and before was more or less the same as in C11, though the verbiage describing it in C still uses 'sequence points' whereas C++11 and later does not.

                      – Jonathan Leffler
                      Nov 30 '18 at 5:34








                    1




                    1





                    The question is tagged C++ and not C, which is good because the behaviour in C++17 is quite different from the behaviour in older versions — and bears no relation to the behaviour in C11, C99, C90, etc. Or bears very little relation to it. On the whole, I'd suggest removing this. More significantly, we need to find the equivalent Q&A for C and make sure it is OK (and notes that C++17, in particular, changes the rules — the behaviour in C++11 and before was more or less the same as in C11, though the verbiage describing it in C still uses 'sequence points' whereas C++11 and later does not.

                    – Jonathan Leffler
                    Nov 30 '18 at 5:34





                    The question is tagged C++ and not C, which is good because the behaviour in C++17 is quite different from the behaviour in older versions — and bears no relation to the behaviour in C11, C99, C90, etc. Or bears very little relation to it. On the whole, I'd suggest removing this. More significantly, we need to find the equivalent Q&A for C and make sure it is OK (and notes that C++17, in particular, changes the rules — the behaviour in C++11 and before was more or less the same as in C11, though the verbiage describing it in C still uses 'sequence points' whereas C++11 and later does not.

                    – Jonathan Leffler
                    Nov 30 '18 at 5:34



                    Popular posts from this blog

                    Liquibase includeAll doesn't find base path

                    How to use setInterval in EJS file?

                    Petrus Granier-Deferre