Compound expressions, conditional expressions and casts are allowed as lvalues provided their operands are lvalues. This means that you can take their addresses or store values into them.
Standard C++ allows compound expressions and conditional expressions as lvalues, and permits casts to reference type, so use of this extension is deprecated for C++ code.
For example, a compound expression can be assigned, provided the last expression in the sequence is an lvalue. These two expressions are equivalent:
(a, b) += 5 a, (b += 5)
Similarly, the address of the compound expression can be taken. These two expressions are equivalent:
&(a, b) a, &b
A conditional expression is a valid lvalue if its type is not void and the true and false branches are both valid lvalues. For example, these two expressions are equivalent:
(a ? b : c) = 5 (a ? b = 5 : (c = 5))
A cast is a valid lvalue if its operand is an lvalue. A simple assignment whose left-hand side is a cast works by converting the right-hand side first to the specified type, then to the type of the inner left-hand side expression. After this is stored, the value is converted back to the specified type to become the value of the assignment. Thus, if a has type char *, the following two expressions are equivalent:
(int)a = 5 (int)(a = (char *)(int)5)
An assignment-with-arithmetic operation such as “+=” applied to a cast performs the arithmetic using the type resulting from the cast, and then continues as in the previous case. Therefore, these two expressions are equivalent:
(int)a += 5 (int)(a = (char *)(int) ((int)a + 5))
You cannot take the address of an lvalue cast, because the use of its address would not work out coherently. Suppose that &(int)f were permitted, where f has type float. Then the following statement would try to store an integer bit-pattern where a floating-point number belongs:
*&(int)f = 1;
This is quite different from what (int)f = 1 would do — that would convert 1 to floating point and store it. Rather than cause this inconsistency, we think it is better to prohibit use of “&” on a cast.
If you really do want an int * pointer with the address of f, you can simply write (int *)&f.