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
.