int x, y; int main() { x++ + ++y; x+++ ++y; x++ +++y; x +++++ y; } 

Why this program does not produce errors for 1 and 2 lines, but gives them for 3 and 4?

    2 answers 2

    The first line will be divided into tokens as follows:

    x , ++ , + , ++ , y .

    What will result in the expression statement with a valid expression (postfix increment x , prefix increment y and binary addition operator).


    The second line is divided into tokens in the same way as the first line, because preprocessing tokens † is calculated using the maximal munch principle, and the maximum valid preliminary token will be ++ , not +++ .

    lex.pptoken # 3.3 :

    If the input stream has been parsed into preprocessing tokens up to a given character:

    • ...
    • ...
    • Otherwise, it could even be a continuation process , even if it was not accepted .

    The third line will be divided into tokens as follows:

    x , ++ , ++ , + , y .

    It differs from the first and second lines because after the 3 basic characters + there is no white space , which in the previous cases separated preliminary tokens + and ++ .

    As a result, we get an expression statement with an invalid expression, since The postfix increment is applied to the result of the postfix increment.

    expr.post.incr # 1 :

    ... The operand shall be a modifiable lvalue . ... The result is a prvalue . ...


    The fourth line is divided into tokens in the same way as the third line, because:

    • white space after x and before y does not affect the calculation of preliminary tokens;
    • the absence of white space after the 2 base character + does not affect the calculation of preliminary tokens in the same way as lines 1 and 2.

    † Read more about the phases of the broadcast can be found here . Then it will become clear why to separate preliminary and ordinary tokens.

       error: lvalue required as increment operand x++ +++y; ^ error: lvalue required as increment operand x +++++ y; ^ 

      Translation: adding a unit is possible only to the addressable variable, not a temporary number.

      Examples of NOT lvalue values ​​and errors:

       ++ ( 2 + 2 ) ; int f ( int ) ; ++ f ( 1 ) ; 

      The first examples are resolved by the compiler using the priority of operations. Increment ++ has a very high priority and is calculated as follows:

        x++ + ++y; => (x++) + (++y); x+++ ++y; => (x++)+ (++y); 

      Erroneous so:

       x++ +++y; => (x++) (++(+y)); x +++++ y; => (x ++)(++(+ y)); 

      where +y or -y is no longer an lvalue value.

      The return value of the postfix operator and the prefix operator is also different. ++y returns lvalue , and y++ returns an rvalue . Therefore:

       ++(++y) - OK ++(y++) - error 
      • Translation, frankly, leaves much to be desired. And in general, the answer does not respond to anything. - freim
      • In this example, the “priority of operations” does not appear anywhere. The priority of operations comes into play only when there are two competing operations (that is, potentially working with the same operand, which leads to an external syntax ambiguity). The priority of operations comes into play only when 1) a prefix unary operation competes with a postfix unary operation or when 2) a unary operand competes with a binary one. In this case, there is no “competition” anywhere and the parsing is completely unequivocal without the participation of any priorities. - AnT