Undefined Behavior. ..

Discussion in 'C Programming' started by coolguyaroundyou, Nov 15, 2008.

  1. Will the following statement invoke undefined behavior :

    a^=b,b^=a,a^=b ;

    given that a and b are of int-type ??

    Be cautious, I have not written a^=b^=a^=b ; which, of course, is
    undefined. I am having some confusion with the former statement!

    Also, state the reason for the statement being undefined!
     
    coolguyaroundyou, Nov 15, 2008
    #1
    1. Advertisements

  2. No, because the comma operator constitutes a sequence point
    6.5.17.1
    The left operand of a comma operator is evaluated as a void expression;
    there is a sequence point after its evaluation.

    Bye, Jojo
     
    Joachim Schmitz, Nov 15, 2008
    #2
    1. Advertisements

  3. <<Be cautious, I have not written a^=b^=a^=b ; which, of course, is
    undefined. I am having some confusion with the former statement!>>

    I think this expression is valid as assignment operator is evaluated
    from right to left so it is parsed as
    (a^=(b^=(a^=b)))
    above expression swaps two numbers
    please correct me if i am wrong...
     
    c.lang.myself, Nov 15, 2008
    #3
  4. This is modifying 'a' twice without an intermediate sequence point ->
    undefined behavoir

    Bye, Jojo
     
    Joachim Schmitz, Nov 15, 2008
    #4
  5. coolguyaroundyou

    maverik Guest

    6.5.17

    1.
    expression:
    assignment-expression
    expression , assignment-expression

    2.
    The left operand of a comma operator is evaluated as a void
    expression; there is a sequence point after its evaluation. Then the
    right operand is evaluated; the result has its type and value.

    So, you have:

    a^=b, b^=a, a^=b
    [expression][assignment-expression]
    |
    a^=b, b^=a
    [expression][assignment-expression]
    |
    a^=b
    [assignment-expression]

    OTOH, a^=b, b^=a, a^=b
    [left operand] [right operand]

    Left operand evaluted as void, and comma epression has a type and
    value of right operand: a^=b.
    But left operand if: a^=b, b^=a
    And again: a^=b, b^=a
    [left operand] [right operand]
    Left operand evaluted as void, and comma epression has a type and
    value of right operand: b^=a.

    So, the sequnce should be like:
    evalute a^=b, then b^=a, then a^=b.
    You should get the same result as in this case:

    a^=b;
    b^=a;
    a^=b;
     
    maverik, Nov 15, 2008
    #5
  6. coolguyaroundyou

    James Kuyper Guest

    That's perfectly safe. As a stand-alone statement, it is exactly
    equivalent to

    a^=b;
    b^=a;
    a^=b;

    The use of the comma operator is only needed in cases like if(A; B; C),
    where A, B, and C can only be a single statement. In any other context,
    I'd recommend breaking it out into three separate statements, but only
    for the sake of clarity - it's perfectly legal as a single statement.
    6.5p2: "Between the previous and next sequence point an object shall
    have its stored value modified at most once by the evaluation of an
    expression".

    Because the second version violates a "shall" occurring outside of a
    "Constraints" section, the behavior is undefined.

    The key difference between the two statements is the presence of the ','
    operators in the first version. The ',' operator inserts a sequence
    point separating it's two operands.
     
    James Kuyper, Nov 15, 2008
    #6
  7. sorry,I am still not able to get it...

    now again consider a^=b^=a^=b
    when compiler see this expression it starts from RHS as assignment
    operator is right associative
    so first it has to calculate rightmost a^=b then value of a must have
    to change....it porceedes then to calculate b^=a ..then again a^=b....

    as we can also use a=b=3;
    Do you mean that after right most a^=b,we can not be sure that value
    of a is changed till we get sequence point...
    but a=b=3 is valid

    Please clear my confusion...
    thanks,
     
    c.lang.myself, Nov 15, 2008
    #7
  8. coolguyaroundyou

    maverik Guest

    Ok, I mean this: a^=b,b^=a,a^=b; of course
     
    maverik, Nov 15, 2008
    #8
  9. coolguyaroundyou

    vippstar Guest

    What don't you get?
    Wrong, when the compiler sees that expression, he can do whatever he
    wants because that expression invokes undefined behavior.
    Uh, no, it's UB.
    Uh, no, it's UB.
    Uh, no, it's UB.
    That's different than the former expression, because in that
    expression a and b are modified only once between sequence points.
    No, a^=b^=a^=b invokes UB and if you have that in your code, you can't
    be sure of anything at all.
    For the reasons I explained before. Now I have a question: How the
    hell do you know that a = b = 3 is valid if you don't understand and
    you're confused?
     
    vippstar, Nov 15, 2008
    #9
  10. When the compiler sees that expression, it cannot be sure whether it will
    be executed. It must compile the code, and if the program reaches the
    point where the expression is evaluated, _then_ the behaviour is
    undefined. The compiler cannot do whatever it wants. The compiler can make
    the resulting code do whatever it wants.
    Uh, yes, ^= is right associative. The behaviour is undefined but that does
    not affect parsing.
     
    Harald van Dijk, Nov 15, 2008
    #10
  11. coolguyaroundyou

    vippstar Guest

    What ELSE could the compiler do other than having the output be
    whatever he wants? I don't think you've really added to what I said.
    Well, UB is when the standard doesn't impose any requirements for the
    behavior of the implementation. You'd argue that 'parsing' is not
    included in 'behavior'? You might be right but I'd like quotes from
    the standard to trust you. (you are certainly credible, but c&v from
    the standard is always nice)
     
    vippstar, Nov 15, 2008
    #11
  12. coolguyaroundyou

    James Kuyper Guest

    The standard quite explicitly says that the consequences of undefined
    behavior can include failing to compile, which clearly indicates that it
    can precede execution of the relevant code. The standard does not
    explain this in any detail, but I believe that the relevant rule is that
    the undefined behavior is allowed at any point after execution of the
    relevant code becomes inevitable.

    Example:

    if(some condition)
    a^=b^=a^=b;

    For code like this, the behavior of the code becomes undefined as soon
    as it becomes inevitable that the if() clause will be executed. This
    means that at points in the code prior the if() statement, the compiler
    is allowed to generate code using optimizations that only work if the
    if-condition is not true. As a result, those optimizations may cause
    your code to misbehave long before evaluation of the offending statement.
     
    James Kuyper, Nov 15, 2008
    #12
  13. It does quite explicitly say so, but there is a distinction between
    compile-time undefined behaviour and run-time undefined behaviour (not
    spelled out in the standard, but made explicit in DRs). This is run-time
    undefined behaviour, where refusing to compile is permitted only if the
    compiler can prove that the code would always be executed.
    I agree with this.
     
    Harald van Dijk, Nov 15, 2008
    #13
  14. A non-conforming compiler could give an error message and refuse to
    compile any program containing a^=b^=a^=b, but a conforming compiler is
    not allowed to do so (or at least not always).
    Yes, but to get to the part where the standard says the behaviour is
    undefined you need to have already parsed the expression. I can't give an
    exact chapter and verse, but can you explain how you can determine that
    the behaviour is undefined without parsing?
     
    Harald van Dijk, Nov 15, 2008
    #14
  15. coolguyaroundyou

    vippstar Guest

    Wrong, a conforming compiler can reject that code. The reason might be
    quite different than the expression, but it serves more like an excuse
    to reject this. For example, the compiler could claim (assuming a, b,
    int) that the source exceeds the environmental limits.
    If I understand, what you're saying is that the semantics of something
    are not affected by UB, well that's wrong I believe. ^= doesn't need
    to be anything meaningful after the first UB in source code.
     
    vippstar, Nov 15, 2008
    #15
  16. Heh, that's nasty. I suppose it has to also reject a^=b^=c^=d, then, to
    cover up its lie? I can't think of a limit right now that a^=b^=a^=b might
    exceed that a^=b^=c^=d doesn't, and if you can, then I can try to come up
    with another valid example that also exceeds that limit. :)
    Yes, that is wrong, and no, that is not what I'm saying.
    To determine that a^=b^=a^=b modifies a at all, you need to already have
    determined that this is an assignment-expression with only a as its left
    operand. In other words, that it is equivalent to a^=(b^=(a^=b)) instead
    of ((a^=b)^=a)^=b. The latter is simply a constraint violation and
    attempts to modify a only once: the other ^= operators attempts to modify
    the result of an assignment.
     
    Harald van Dijk, Nov 15, 2008
    #16
  17. coolguyaroundyou

    vippstar Guest

    There's no need for that, a conforming compiler can also reject
    a^=b^=c^=d for the same reason.
    Also, a compiler doesn't have to cover up its lies as there's no such
    requirement. My point is that a conforming compiler can reject
    anything, and a compiler can output anything when UB is encountered. I
    believe that to be true, and I think the requirements the standard
    sets on an implemenations agree with those words.
    Alright then...
    Hmm... then yes, I was wrong on the original matter.
     
    vippstar, Nov 15, 2008
    #17
  18. Now i am able to get it.
    I know a=b=3 is valid as i read it in my C text book but i had not
    read other undefined statement in this thread so i was confused about
    it...
     
    c.lang.myself, Nov 15, 2008
    #18
  19. coolguyaroundyou

    vippstar Guest

    Which book and page?
     
    vippstar, Nov 15, 2008
    #19
  20. K n R page-48...in function strcat
    2nd line is i=j=0;
     
    c.lang.myself, Nov 15, 2008
    #20
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.