是否有理由使用*&或C&C中的& *?

时间:2016-07-01 19:05:27

标签: c dereference unary-operator addressof

我遇到过一些C代码,它们同时使用引用/解除引用(或者你选择的任何名称)运算符*&,例如{{ 1}}和&*foo。我很困惑。有什么理由这样做吗?

3 个答案:

答案 0 :(得分: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
}

答案 1 :(得分:2)

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

引用C11,章节§6.5.3.2

  

一元&运算符生成其操作数的地址。如果操作数的类型为''type'',   结果有''指向类型''的指针。如果操作数是一元*运算符的结果,   该运算符和&运算符都不会被评估,结果就像两者都一样   省略,除了对运算符的约束仍然适用且结果不是左值。

答案 2 :(得分:0)

  1. &*ptr包含ptr != NULL编译器的提示(否则*ptr将表示未定义的行为)。

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

    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;  // <---
        ...
    }
    
  3. 类似地,&*可能会通过重构更改引入,该更改将lvalue替换为指针。

    重构之前:

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