http://www.embedded.com/story/OEG20010518S0071
http://www.embedded.com/story/OEG20010618S0075
Summary:
An expression yields either an lvalue or an rvalue. Lvalue is something referring to an object of storage. Values which are not lvalues are rvalues.
However, not all lvalues can be used as left operand of assignment operator - lvalues are classified as modifiable lvalues and non-modifiable lvalues. This happened after "const" introduced to C/C++.
Why not regard non-modifiable lvalues as rvalues? The difference is that you can take address of a non-modifiable lvalue, but cannot do the same thing with rvalues. Example:
int const n = 0;
int const *p = &n; //ok
int const *p = &7; //error
int const *p = &n; //ok
int const *p = &7; //error