I tryed to compile old code with new compiler and got the next error:
error: cannot take the address of an rvalue of type 'int'
Here is the example with 2 lines - one that compiles and the other that gives an error
struct mstct {
int myfield;
int myfield2[5];
int myfield3[5];
};
typedef struct mstct db_data_px;
int foo(int a, int b, int c){
//the next code compiles successfully.
unsigned val1 = ((18 == c) ? ((unsigned) & (((db_data_px *) 0)->myfield)) : ((unsigned) & (((db_data_px *) 0)->myfield3[b]))); //successes
//the next code is failing
unsigned val2 = (unsigned) & ((18 == c) ? (((db_data_px *) 0)->myfield) : (((db_data_px *) 0)->myfield3[b]));
return 0; // failing
}
Why the first line compiles and the second is failing ? Why do I need to cast (unsigned) & in both of the select expression and it is not enough to cast only after the select expression is valued ?
In your code
((18 == c) ? (((db_data_px *) 0)->myfield) : (((db_data_px *) 0)->myfield3[b]))
is a conditional expression which does not produce a lvalue.
The above expression gives you an rvalue (non-lvaue) and you cannot use &
operator on that.
To elaborate, quoting C11
standard, chapter §6.5.3.2, Address and indirection operators
The operand of the unary
&
operator shall be either a function designator, the result of a[]
or unary*
operator, or an lvalue that designates an object that is not a bit-field and is not declared with theregister
storage-class specifier.
OTOH, for the result type of the conditional operator, chapter §6.5.15, footnote
A conditional expression does not yield an lvalue.
Just imagine, &5
, not possible.