Expressions in C++ (and in C) evaluate to values, which have different categories (2 in C and in legacy C++, 5 in modern C++). The two basic categories are lvalue and rvalue.
An lvalue is a value that exists somewhere in RAM. it can be assigned to, its address can be taken, etc.
An rvalue is a value that exists, roughly speaking, in CPU. It has no RAM address, and it has no name.
Only lvalue expressions can be on the left side of the assignment operator: 2+2 = 4; will not compile because 2+2 evaluates to an rvalue.
The expression ++y evaluates to an rvalue in C, but to an lvalue in C++.
C++03 §5.3.2[expr.pre.incr]/1
The value is the new value of the operand; it is an lvalue
C++11 §5.3.2[expr.pre.incr]/1
The result is the updated operand; it is an lvalue
For C, it doesn't explicitly say "rvalue", you have to follow a few steps deeper
C89 §3.3.3.1
"The result is the new value of the operand after incrementation. The expression ++E is equivalent to (E+=1)"
C99 §6.5.3.1
"The result is the new value of the operand after incrementation. The expression ++E is equivalent to (E+=1)."
(then, E+=1 is equivalent to E = E+1 per 6.5.16.2, and finally in 6.5.16/3 it says: "An assignment expression has the value of the left operand after the assignment, but is not an lvalue.")
I just verified it in C++03. Now that I think about it it kind of makes sense since the input operand must be an lvalue. The operation strictly just increments its value.
@bbgst xvalue (expiring value), prvalue (pure rvalue), and glvalue (generalized lvalue). Technically, there are only three value categories: lvalue, xvalue, prvalue. The other two (rvalue and glvalue) are combinations.