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.
++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.
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.
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.)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With