I've come across some C code that make use of the reference/dereference (or whatever you choose to call them) operators, *
and &
, at the same time, like &*foo
and *&bar
. I'm puzzled by it. Is there any reason to do this?

- 133,132
- 16
- 183
- 261

- 554
- 5
- 17
-
2Can you show us an example case (_not example code_)? – Sourav Ghosh Jul 01 '16 at 19:07
-
It's being used in simple variable assignments. – qsfzy Jul 01 '16 at 19:09
3 Answers
Yes, they can be used meaningfully: a valid use case is in macro definitions to check that the macro argument matches the requirements.
&*foo
verifies that foo
is a pointer type (possibly after an implicit conversion from an array or function type).
*&foo
verifies that foo
is an lvalue expression.
For example, admittedly an example so simple that it might be a bit of macro abuse:
void f(int *);
#define F(x) (f(&*(x)))
void g(int *);
#if A
#define G(x) (g(x), (x)=0)
#elif B
#define G(x) (g(*&(x)))
#endif
void h(int *p, int i) {
f(p); // okay
F(p); // still okay, does the same thing as f(p)
f(i); // typically just a compiler warning
F(i); // pretty much always a compiler error
g(p); // okay
G(p); // okay
g(p+0); // okay
G(p+0); // error if A because of the modification
// should be an error if B even without modification
}
-
1Could you please provide more concrete examples? Will help to understand your answer better. Thanks. – Stanislav Pankevich Jul 01 '16 at 20:40
-
-
Very helpful, thanks. Could you also add an example for `*&foo verifies that foo is an lvalue expression.`? – Stanislav Pankevich Jul 01 '16 at 20:50
-
@StanislavPankevich I can create an example where it's technically valid, but I don't have one readily available where it has any benefit. I'll try to add one later. – Jul 01 '16 at 20:54
-
The only meaningful reason to do so is to stop treating the expression as an lvalue.
Quoting C11
, chapter §6.5.3.2
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.

- 133,132
- 16
- 183
- 261
-
4When would you want to do that? I've never said to myself, "I sure wish this wasn't an lvalue." – yellowantphil Jul 01 '16 at 19:13
-
@yellowantphil That's dependent, but in case of equality checks, it can help detecting `=` vs `==` issues. – Sourav Ghosh Jul 01 '16 at 19:16
-
3@SouravGhosh I haven't ever seen people write `&*p1 == &*p2` to catch that. Have you? – Jul 01 '16 at 19:18
-
@hvd no, I did not, but that's still possible. And echoing your question, I asked for the example to OP, in the first place. :) – Sourav Ghosh Jul 01 '16 at 19:20
&*ptr
contains a hint for the compiler thatptr != NULL
(since otherwise*ptr
would mean undefined behavior).*&
may be simply a result of a maintenance change where an auxiliary pointer variable was eliminated:struct { int i; double } x; void foo() { int* ip = &x.i; ... *ip = 1; ... }
Straightforwardly replacing in the above code
ip
with&x.i
results in code that can give birth to such a question on StackOverflow:struct { int i; double } x; void foo() { ... *&x.i = 1; // <--- ... }
Similarly
&*
may be introduced by a refactoring change that replaced lvalue with a pointer.Before refactoring:
int main() { struct sockaddr_in serv_addr; ... bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)); ... }
After extracting the server setup code into a function of its own:
void setup_server(struct sockaddr_in* serv_addr) { ... bind(sockfd, (struct sockaddr *) &*serv_addr, sizeof(*serv_addr)); ... } int main() { struct sockaddr_in serv_addr; ... setup_server(&serv_addr); ... }

- 31,443
- 4
- 72
- 97