Why can you write a = a + 1; in C but not a + 1 = a; — what's the difference between an lvalue and an rvalue?
An lvalue names a storage location you can assign into (it has an address); an rvalue is just a value. Assignment needs an lvalue on the left, so 2 = a or a + 1 = a are illegal.
Every assignment has the form LHS = RHS, and the two sides are read differently — even when they contain the same variable:
- The left-hand side must be an lvalue: something that designates a place in memory (a variable,
*p,arr[i],s.field). It answers "where do I store the result?" - The right-hand side is an rvalue: an expression evaluated down to a plain value. It answers "what value?"
That split is why one name means two things depending on the side:
a = a + 1;
// ^^^^^ RHS: read a's current value, add 1 → a plain number
// ^ LHS: the address where a lives → store the result here
In the memory-alias model, on the right a means "the contents of a's cell"; on the left a means "a's cell itself". So these have no storage location to write into and are rejected by the compiler:
2 = a + b; // a literal has no address
a + 1 = a; // a+1 is a temporary value, not a place
Tip: "lvalue" originally meant "left-of-assignment value", but the real test is addressability: &expr is legal exactly when expr is an lvalue. That's why &a works while &(a + 1) and &5 don't.