StoryTeller explained already where in the standard why for your example, the expression (i)
is still an lvalue, but I believe you are being hung up on the spec for no reason so allow me to try to address your concerns.
I checked the code and the rules, and found this: in assignment
expression semantics:
An assignment operator shall have a modifiable lvalue as its left
operand.
An assignment expression has the value of the left operand after the
assignment, but is not an lvalue.
The entire quote is referring to the assignment expression as a whole, not the lhs or rhs.
"An assignment operator shall have a modifiable lvalue as its left operand." states that the lhs must be a modifiable lvalue.
"An assignment expression has the value of the left operand after the assignment, but is not an lvalue." states that the whole assignment expression itself as a result has the value of the lhs and is itself an rvalue.
So the following are all true:
int i;
i <- modifiable lvalue
(i) = 1;
(i) <- modifiable lvalue (per StoryTeller's answer)
1 <- rvalue
((i) = 1) <- rvalue
Why is this significant? Consider the following:
int i = 0, j = 0, k = 0;
i = j = k = 1;
// parsed as `i = (j = (k = 1))`
// the expression `k = 1` has the value `1` and is an rvalue
// the expression `j = (k = 1)` has the value `1` and is an rvalue
(i = 2) = 3;
// is invalid, the expression `i = 2` is an rvalue, but it may not be the lhs of the assignment
In my case, the there are two assignment expressions: (i) = 1
and i
in
parentheses. So the (i)
should be a rvalue.
No that is incorrect. (i) = 1
is the only assignment expression. There are two subexpressions (one parenthesized identifier (i)
and a numeric constant 1
).