有理由在C代码中使用*&或&*吗?



我遇到一些C代码,利用引用/解引用(或任何你选择叫他们)操作符,*&,在同一时间,像&*foo*&bar。我对此感到困惑。有什么理由这样做吗?

是的,它们可以被有意义地使用:一个有效的用例是在宏定义中检查宏参数是否与需求匹配。

&*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
}

这样做的唯一有意义的原因是停止将表达式视为左值

引用C11, chapter§6.5.3.2

一元&运算符返回其操作数的地址。如果操作数的类型为 " type " ,结果类型为 "指向类型" 的指针"。如果操作数是一元*操作符的结果,既不计算该操作符,也不计算&操作符,结果就好像两者都计算了一样

  1. &*ptr向编译器提示ptr != NULL(否则*ptr将意味着未定义行为)。

  2. *&可能只是一个维护更改的结果,其中一个辅助指针变量被消除了:

    struct {
        int i;
        double
    } x;
    void foo() {
        int* ip = &x.i;
        ...
        *ip = 1;
        ...
    }
    

    在上面的代码中直接用&x.i替换ip会导致在StackOverflow上产生这样的问题:

    struct {
        int i;
        double
    } x;
    void foo() {
        ...
        *&x.i = 1;  // <---
        ...
    }
    
  3. 同样,&*也可以通过重构更改来引入,将左值替换为指针。

    重构前

    :

    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);
        ...
    }
    

相关内容

  • 没有找到相关文章

最新更新