If for &*x both * and & are not evaluated, then why not have the same rule for *&x?

Viewed 77

C2x, 6.5.3.2 Address and indirection operators, Semantics, 3:

The unary & operator yields the address of its operand. If the operand has type "type", the result has type "pointer to type". If the operand is the result of a unary * operator, neither that operator nor the & operator is evaluated and the result is as if both were omitted, except that the constraints on the operators still apply and the result is not an lvalue.

If for &*x both * and & are not evaluated, then why not have the same rule for *&x? I.e. the same rule for the unary * operator.

2 Answers

Because the value may change, reference not.

int foo(volatile int x)
{
    return *&x;
}


int *bar(volatile int *x)
{
    return &*x;
}
foo:
        mov     DWORD PTR [rsp-4], edi
        mov     eax, DWORD PTR [rsp-4]
        ret
bar:
        mov     rax, rdi
        ret

Interesting this will be evaluated (& only):

int *bar(int * volatile x)
{
    return &*x;
}

So it is invalidating my previous opinion

The equivalence between x and &*x is enforced by N721, which makes some code previously having UB well-defined.

IIUC when x is a valid lvalue or a function (not considered as an lvalue in C), *&x is already equivalent to x without any additional rule. Compilers may treat them differently, but they are free not to do this.

Even if x is volatile-qualified, &x does not perform volatile read, and only produces a pointer value of type volatile T* (the type itself is not volatile). And then the indirection from it itself does not form a volatile access, only using the result would, which is same to the using of the simple x.

Related