Why according to the standard is a++ = b;
disallowed, while c[i++] = d;
is permitted?
(Obviously, a++ = b;
would be bad style, but this is a question about a close reading of the C language standard.)
Here is the obligatory minimal example:
#include <stdio.h>
int main(void)
{
int a = 10;
int b = 20;
int i = 1;
int c[] = {30, 40};
int d = 50;
a++ = b; // error
c[i++] = d;
printf("%d\n", a); // [21]
printf("%d\n", b); // 20
printf("%d\n", i); // 2
printf("%d\n", c[0]); // 30
printf("%d\n", c[1]); // 50
printf("%d\n", d); // 50
return 0;
}
GCC emits the following error, when compiling this with -std=c90
or -std-c17
:
error: lvalue required as left operand of assignment
According to K&R (2e), A7.3.4 and A7.4.1
The result [of postfix/prefix
++
or--
] is not an lvalue.
a++
is considered to be not an lvalue, but from what wording does it explicitly follow that c[i++]
is an lvalue? Turning to the C11 standard, I can't find any provisions about either.
For what it's worth: If it weren't disallowed, I would interpret a++ = b;
as a = b; a = a+1;
.
Edit:
Some people have (justifiedly) asked why one would semantically assume a statement like a++ = b;
to make sense.
I often try to convert tricky syntactic constructs into something equivalent-but-simpler. (Let's all admit that pre- and post-increment/decrement operators aren't just tricky; they're a syntactic catastrophe: they can be deeply embedded in a statement but have the effect of something having to be executed before or after.) I was generally going with the assumption that any non-pathological statement of the form
statement(
++w
,--x
,y++
,z--
)
is equivalent to
w += 1;
x -= 1;
statement(w
,x
,y
,z
)
y += 1;
z -= 1;
where the pre- and post-statement assignments are ordered in an implementation-defined manner. Of course the question is what counts as "non-pathological" (or whether we should even define it as "cases for which the order among the pre-increments and among the post-increments doesn't matter"), but, putting this concern aside for a moment, it is not unreasonable for a programmer to assume that pre- and post-incremented/decremented expressions are otherwise syntactically equivalent to their corresponding forms with these operators removed.
Saying that "such operators strip their argument expressions of their lvalue quality" is entirely valid and does answer my question, but:
- If this assumption isn't built into one's mindset, other interpretations (such as what I wrote above) are conceivable. (That is, from a language design perspective (and in my opinion), pre-/post-increment/decrement expressions losing their lvalue quality is not a syntactic necessity.)
- To me it seems a bit that the wording quoted from K&R ("The result [of postfix/prefix
++
or--
] is not an lvalue.") was put in simply to disallow assignments likea++ = b;
.