Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is "++i++" invalid while (++i)++ is valid?

Let's consider the following code:

int main() {
    int i = 2;
    int b = ++i++;
    return 3;
}

It compiles with the following with an error:

<source>: In function 'int main()':

<source>:3:16: error: lvalue required as increment operand

    3 |     int b = ++i++;

      |                ^~

This sounds fair to me. Postfix increment has higher priority than prefix increment, so the code is parsed as int b = ++(i++); and i is an rvalue. Hence the error.

Let's now consider this variant with parenthesis to override default priorities:

int main() {
    int i = 2;
    int b = (++i)++;
    return 3;
}

This code compiles and returns 3. On its own, this sounds fair to me but it seems in contradiction with the first code.

The question: why (++i) is an lvalue when i is not?

Thanks!

UPDATE: the error message shown above was from gcc (x86-64 9.2). Here is the exact rendering: error with gcc

Clang x86-64 9.0.0 has a quite different message: error with clang

<source>:3:13: error: expression is not assignable

    int b = ++i++;

            ^ ~~~

With GCC, you get the impression that the problem is with the postfix operator and you can then wander why ++i is OK while i is not, hence my question. With Clang it is clearer that the problem is with the prefix operator.

like image 718
Bktero Avatar asked Nov 13 '19 15:11

Bktero


People also ask

Is ++ i ++ valid in C?

++i++ is an error by the current definition of C. The language could easily be changed to have an explicit rule for this expression (produce the value ((i+=2),i-1) ), but given how often it would be used, it's hardly worth the effort.

How to fix invalid syntax error Python?

You can clear up this invalid syntax in Python by switching out the semicolon for a colon. Here, once again, the error message is very helpful in telling you exactly what is wrong with the line.


2 Answers

i and ++i are both lvalues, but i++ is an rvalue.

++(i++) cannot be valid, as the prefix ++ is being applied to i++, which is an rvalue. But (++i)++ is fine because ++i is an lvalue.

Note that in C, the situation is different; i++ and ++i are both rvalues. (This is an example of why people should stop assuming that C and C++ have the same rules. People insert these assumptions into their questions, which must then be refuted.)

like image 194
Brian Bi Avatar answered Nov 15 '22 15:11

Brian Bi


This declaration

int b = ++i++;

is equivalent to

int b = ++( i++ );

The postfix increment operator returns the value of the operand before increment.

From the C++ 17 Standard (8.2.6 Increment and decrement)

1 The value of a postfix ++ expression is the value of its operand...The result is a prvalue.

While the unary increment operator returns lvalue after its increment. So this declaration

int b = (++i)++;

is valid. You could for example write

int b = (++++++++i)++;

From the C++ 17 Standard (8.3.2 Increment and decrement)

1 The operand of prefix ++ is modified by adding 1. The operand shall be a modifiable lvalue. The type of the operand shall be an arithmetic type other than cv bool, or a pointer to a completely-defined object type. The result is the updated operand; it is an lvalue, and it is a bit-field if the operand is a bit-field....

Pay attention that in C the both operators return a value instead of lvalue. So in C this declaration

int b = (++i)++;

is invalid.

like image 22
Vlad from Moscow Avatar answered Nov 15 '22 14:11

Vlad from Moscow