What is the difference between a sequence point and operator precedence?

前端 未结 3 1984
南笙
南笙 2021-01-31 03:50

Consider the classical sequence point example:

i = i++;

The C and C++ standards state that the behavior of the above expression is undefined be

3条回答
  •  后悔当初
    2021-01-31 04:30

    Operator precedence and order of evaluation are two different things. Let's have a look at them one by one:

    Operator precedence rule: In an expression operands bound tighter to the operators having higher precedence.

    For example

    int a = 5;
    int b = 10;
    int c = 2;
    int d;
    
    d = a + b * c;  
    

    In the expression a + b * c, precedence of * is higher than that of + and therefore, b and c will bind to * and expression will be parsed as a + (b * c).

    Order of evaluation rule: It describes how operands will be evaluated in an expression. In the statement

     d = a>5 ? a : ++a; 
    

    a is guaranteed to be evaluated before evaluation of ++b or c.
    But for the expression a + (b * c), though * has higher precedence than that of +, it is not guaranteed that a will be evaluated either before or after b or c and not even b and c ordered for their evaluation. Even a, b and c can evaluate in any order.

    The simple rule is that: operator precedence is independent from order of evaluation and vice versa.

    In the expression i = i++, higher precedence of ++ just tells the compiler to bind i with ++ operator and that's it. It says nothing about order of evaluation of the operands or which side effect (the one by = operator or one by ++) should take place first. Compiler is free to do anything.

    Let's rename the i at left of assignment be il and at the right of assignment (in the expression i++) be ir, then the expression be like

    il = ir++     // Note that suffix l and r are used for the sake of clarity.
                  // Both il and ir represents the same object.  
    

    Now compiler is free to evaluate the expression il = ir++ either as

    temp = ir;      // i = 0
    ir = ir + 1;    // i = 1   side effect by ++ before assignment
    il = temp;      // i = 0   result is 0  
    

    or

    temp = ir;      // i = 0
    il = temp;      // i = 0   side effect by assignment before ++
    ir = ir + 1;    // i = 1   result is 1  
    

    resulting in two different results 0 and 1 which depends on the sequence of side effects by assignment and ++ and hence invokes UB.

提交回复
热议问题