11

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 ?

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
yehudahs
  • 2,488
  • 8
  • 34
  • 54
  • can't see what the difference but in this case it is c – yehudahs Jan 27 '16 at 15:49
  • The cast is irrelevant. Shorter code that illustrates the issue: `int x, y; int* p = true ? &x : &y; int* q = &(true ? x : y)`. – molbdnilo Jan 27 '16 at 15:56
  • @yehudahs Did you try compiling as C and C++? You may see a difference then. – juanchopanza Jan 27 '16 at 15:57
  • actually, NONE of the posted code compiles. (always enable all warnings when compiling. (for gcc, at a minimum use: `-Wall -Wextra -pedantic` (I also use: `-Wconversion -std=c99`) ) the result is 5 warnings and one error. I suspect your referencing the `error` message: " lvalue required as unary '&' operand" but your question mentions not being able to get address of an rvalue. So I'm a bit confused at to what your actually asking about – user3629249 Jan 28 '16 at 22:17
  • the posted code is trying to get a value off address 0. This is (almost) certain to result in a memory access error, resulting in a seg fault event. – user3629249 Jan 28 '16 at 22:21

1 Answers1

11

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.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261