Search code examples
cpointersoperatorsaddress-operator

Why can't I use `&&a` in C?


int main(int argc, char * argv[]) {
  int       a = 10;
  int *    sp = &a;
  int * * dp1 = &sp;
  int * * dp2 = &&a;           // NG
  int * * dp3 = &(&a);         // NG
  int * * dp4 = &((int *) &a); // NG
}
$ cc test.c
test.c: In function ‘main’:
test.c:6:17: error: lvalue required as unary ‘&’ operand
   int * * dp3 = &(&a);         // NG
                 ^
test.c:7:17: error: lvalue required as unary ‘&’ operand
   int * * dp4 = &((int *) &a); // NG
                 ^
test.c:5:3: error: label ‘a’ used but not defined
   int * * dp2 = &&a;           // NG
   ^

Solution

  • Why can't I use &&a

    Because & gives you the address of a varibale and &a is not a variable.

    The C 11 Draft specifies the following:

    6.5.3.2 Address and indirection operators

    Constraints

    1 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.

    [...]

    Semantics

    3 The unary & operator yields the address of its operand. [...]

    To get around this "limitation" one could introduce temporary storage using a compound literal like this (assuming C99 at least):

    int a = 42; 
    int ** ppa = &((int *){&a});
    

    As a side note referring to the error message below:

    test.c:5:3: error: label ‘a’ used but not defined
       int * * dp2 = &&a;           // NG
       ^
    

    gcc (and probably others) define an extension to the C-Standard allowing the use of the && operator on a single operant if the operant identifies a label. (More on this here: https://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html)

    Example:

    void * pv = &&lbl;
    
    goto *pv;
    
    /* some dead code  */
    
    lbl:;
    
    /* living code again here */