我遇到了一些 C 代码,它们使用引用/取消引用(或您选择的任何名称)运算符,*
并且&
同时像&*foo
and *&bar
。我对此感到困惑。有什么理由这样做吗?
问问题
231 次
3 回答
15
是的,它们可以有意义地使用:有效的用例在宏定义中,以检查宏参数是否符合要求。
&*foo
验证它foo
是指针类型(可能在从数组或函数类型进行隐式转换之后)。
*&foo
验证这foo
是一个左值表达式。
例如,不可否认的一个例子很简单,以至于它可能有点滥用宏:
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
}
于 2016-07-01T19:10:33.753 回答
2
于 2016-07-01T19:12:04.233 回答
0
&*ptr
包含对编译器的提示ptr != NULL
(否则*ptr
将意味着未定义的行为)。*&
可能只是维护更改的结果,其中删除了辅助指针变量:struct { int i; double } x; void foo() { int* ip = &x.i; ... *ip = 1; ... }
ip
在上面的代码中直接替换为&x.i
可以在 StackOverflow 上产生这样一个问题的代码:struct { int i; double } x; void foo() { ... *&x.i = 1; // <--- ... }
类似地
&*
,可以通过用指针替换左值的重构更改引入。重构前:
int main() { struct sockaddr_in serv_addr; ... bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)); ... }
将服务器设置代码提取到自己的函数中后:
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); ... }
于 2016-07-03T20:29:22.307 回答