sequence points

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Kai-Uwe Bux

    #1

    sequence points

    Please consider

    #include <iostream>

    int main ( void ) {
    int a = 0;
    a = ( (a = 5), 4 ); // (*)
    std::cout << a << '\n';
    }

    I would like to determine whether line(*) has undefined behavior (modifying
    a variable twice between sequence points).

    What I think is this: We have an assignment expression

    lhs = rhs

    where the right hand side is this:

    (a = 5), 4

    I note that the comma will introduce a sequence point that separates the
    side-effects of a=5 from the side-effects of 4. The main question therefore
    is whether the right hand side

    (a = 5), 4

    can have a value before the side effects of its evaluation take place. My
    understanding of the standard is that sequence points only separate side
    effect but do not tell us anything about how, where and when values of
    expressions are established. However, if that understanding is correct, the
    abstract machine would be allowed to predict that the right hand side will
    have value 4 and perform the side effect of the ambient assignment

    lhs = rhs

    before the side effects of the rhs take place. Along this possible path of
    execution, the value of a would be modified twice. Thus, as of now, I
    believe that line (*) has undefined behavior.


    However, I am not sure about this interpretation of the standard; and I
    would appreciate your help. (In fact, I hope that I am wrong.)


    Note that similar considerations would apply to:

    a = f();

    Is it guaranteed that the side-effects of evaluating f() take place before
    the value of a is changed? or would a conforming implementation allowed to
    put all side-effects of f() on hold until it knows the value, perform the
    assignment, and then run the side-effects of f()?



    Thanks

    Kai-Uwe Bux
  • =?UTF-8?B?RXJpayBXaWtzdHLDtm0=?=

    #2
    Re: sequence points

    On 2007-10-14 22:47, Kai-Uwe Bux wrote:
    Please consider
    Note that similar considerations would apply to:
    >
    a = f();
    >
    Is it guaranteed that the side-effects of evaluating f() take place before
    the value of a is changed? or would a conforming implementation allowed to
    put all side-effects of f() on hold until it knows the value, perform the
    assignment, and then run the side-effects of f()?

    The standard says that "[o]nce the execution of a function begins, no
    expressions from the calling function are evaluated until execution of
    the called function has completed." With a footnote adding that "[i]n
    other words, function executions do not interleave with each other." I
    interpret that as though all side-effects of a function must be complete
    before "returning" .

    --
    Erik Wikström

    Comment

    • Lance Diduck

      #3
      Re: sequence points

      On Oct 14, 4:47 pm, Kai-Uwe Bux <jkherci...@gmx .netwrote:
      Please consider
      >
      #include <iostream>
      >
      int main ( void ) {
      int a = 0;
      a = ( (a = 5), 4 ); // (*)
      std::cout << a << '\n';
      }
      >
      I would like to determine whether line(*) has undefined behavior (modifying
      a variable twice between sequence points).
      >
      What I think is this: We have an assignment expression
      >
      lhs = rhs
      >
      where the right hand side is this:
      >
      (a = 5), 4
      >
      I note that the comma will introduce a sequence point that separates the
      side-effects of a=5 from the side-effects of 4. The main question therefore
      is whether the right hand side
      >
      (a = 5), 4
      >
      can have a value before the side effects of its evaluation take place. My
      understanding of the standard is that sequence points only separate side
      effect but do not tell us anything about how, where and when values of
      expressions are established. However, if that understanding is correct, the
      abstract machine would be allowed to predict that the right hand side will
      have value 4 and perform the side effect of the ambient assignment
      >
      lhs = rhs
      >
      before the side effects of the rhs take place. Along this possible path of
      execution, the value of a would be modified twice. Thus, as of now, I
      believe that line (*) has undefined behavior.
      >
      However, I am not sure about this interpretation of the standard; and I
      would appreciate your help. (In fact, I hope that I am wrong.)
      >
      Note that similar considerations would apply to:
      >
      a = f();
      >
      Is it guaranteed that the side-effects of evaluating f() take place before
      the value of a is changed? or would a conforming implementation allowed to
      put all side-effects of f() on hold until it knows the value, perform the
      assignment, and then run the side-effects of f()?
      >
      Thanks
      >
      Kai-Uwe Bux
      I would believe that an good optimising compiler would recognize that
      int a=0;
      a=((a=5),4);
      cout<<a;
      would reduce to
      cout<<4;
      since assigning (non volatile)int has no side effects. Whether this is
      correct by the standard (the C standard at that) there is probably no
      consensus. This is like the "is the Return Value Optimization Correct"
      debate? RVO is usually correct,but not always, esp if the copy
      constructor has a side effect. But in practice, people want RVO
      anyway.

      I think you could clarify the question by only considering volatile
      ints. Then mistakes in the assigment sequence
      0,5,4
      may have observalbe consequences. Otherwise, the state of 'a' does
      not have any consequence outside uts own context --i.e there are no
      "side effects".
      Other things to consider:
      if a were not of type int, then
      1) T a=0; //may have side effect in T constructor
      2) a=5 assignment operator could be overloaded to return something
      other that the value of a
      which leads to
      3) the type of the object returned by the expr 'a=5' could itself
      overload operator, producitng a side effect
      and so forth.

      I think the question of correctness is very hairy, and given that few
      developers actually overload , and = to do things sematically
      different that the built in types, even finding a compiler that
      actually was tested for these occurances and actually gets it right
      (given they actaully agree on the interpretation of the standard)
      makes for a very difficult question.


      Comment

      Working...