getting error: cannot take the address of an rvalue of type 'int'

yehudahs picture yehudahs · Jan 27, 2016 · Viewed 22.6k times · Source

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 ?

Answer

Sourav Ghosh picture Sourav Ghosh · Jan 27, 2016

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 the register 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.