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.