【问题标题】:Is there a reason to use *& or &* in C code? [closed]有理由在 C 代码中使用 *& 或 &* 吗? [关闭]
【发布时间】:2016-11-04 06:42:55
【问题描述】:

我遇到了一些 C 代码,它们同时使用了引用/取消引用(或您选择的任何名称)运算符 *&,例如 &*foo 和 @987654324 @。我对此感到困惑。有什么理由这样做吗?

【问题讨论】:

  • 你能给我们看一个例子吗(不是例子代码)?
  • 它被用于简单的变量赋值。

标签: c dereference unary-operator addressof


【解决方案1】:
  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. 类似地,&amp;* 可能会通过将左值替换为指针的重构更改引入。

    重构前:

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

【讨论】:

    【解决方案2】:

    是的,它们可以有意义地使用:有效的用例在宏定义中,以检查宏参数是否符合要求。

    &amp;*foo 验证 foo 是指针类型(可能在从数组或函数类型进行隐式转换之后)。

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

    【讨论】:

    • 您能提供更具体的例子吗?将有助于更好地理解您的答案。谢谢。
    • @StanislavPankevich 这样的事情? :)
    • 非常有帮助,谢谢。您能否也为*&amp;foo verifies that foo is an lvalue expression. 添加一个示例?
    • @StanislavPankevich 我可以创建一个在技术上有效的示例,但我没有现成的示例,它有任何好处。我稍后会尝试添加一个。
    • 拥有一个会很棒。谢谢!
    【解决方案3】:

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

    引用C11,第 6.5.3.2 章

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

    【讨论】:

    • 你想什么时候做?我从来没有对自己说过,“我当然希望这不是左值。”
    • @yellowantphil 这取决于,但在平等检查的情况下,它可以帮助检测 === 问题。
    • @SouravGhosh 我从来没有见过有人写&amp;*p1 == &amp;*p2 来理解这一点。你有吗?
    • @hvd 不,我没有,但这仍然是可能的。为了回应你的问题,我首先向 OP 询问了这个例子。 :)
    猜你喜欢
    • 2014-02-04
    • 2018-08-02
    • 1970-01-01
    • 2011-10-12
    • 1970-01-01
    • 2017-03-23
    • 2017-10-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多