难以理解表达式 (*(&x->y))

Posted

技术标签:

【中文标题】难以理解表达式 (*(&x->y))【英文标题】:Difficulty understanding the expression (*(&x->y)) 【发布时间】:2021-12-17 17:55:53 【问题描述】:

我有以下文件结构。我知道指针需要分配内存。文件 A 由达芬奇生成。主要是我写的。

// File A
typedef struct 
    int v1;
s1;

struct s2
    s1 *p1;
;

extern const struct s2 * const p3;  // Expr 1
#define untilp1() (*(&p3->p1))  // Expr 2

// File main
#include <stdio.h>
#include "FileA.h"
int main()

    int v2 = 10;
    untilp1()->v1 = v2;  // This line results in failure
    return 0;

    

Q1 - 我不明白表达式 1。具体来说,我不明白 expr 1 中使用了这么多 const 关键字。我知道术语 extern 的含义。在这种情况下,我猜一个常量指针p3 是未定义的,未声明的,但编译器知道它指向常量结构s2。它是否正确?如果你能说得更清楚,请详细说明。

Q2 - 我不明白表达式 2。具体来说,我不明白 (*(&amp;p3-&gt;p2)) 发生了什么。我知道#define 的含义。请详细解释一下表达式。

Q3 - 在一般编码中,我分配内存,例如在我声明使用指针之前使用malloc。当这些文件由达芬奇生成时,我不确定这是如何处理的。但是我没有看到我的任何同事使用 malloc 等。有谁知道我是否可以使用p3untilp1()v2 的值分配给v1

谢谢。

【问题讨论】:

Expr 1 表示p3 是一个指向const struct s2const 指针。阅读更多here。 你可能会觉得这个网站很有趣:cdecl Expr 2 将用*(&amp;p3-&gt;p1)-&gt;v1 替换行untilp1()-&gt;v1 = v2; *(&amp;p3-&gt;p1) 只是写 (p3-&gt;p1) 的一种混淆方式。编写此类代码的唯一原因是程序员不知道运算符的优先级。这个代码库似乎有很大的代码味道。 (c) #define untilp1() *(&amp;p3-&gt;p1) 是一个设计糟糕的定义,原因有两个。一,*(&amp;p3-&gt;p1) 等价于p3-&gt;p1,显然没有理由使用前一种形式。第二,众所周知,在宏中使用括号是一种很好的做法,如在#define untilp1() (*(&amp;p3-&gt;p1)) 中,以避免使用宏的优先级问题,这就是在untilp1()-&gt;v1 = v2; 中发生的导致错误的问题。 (-&gt; 的优先级高于*,因此被解析为*((&amp;p3-&gt;p1)-&gt;v1)。)如果该代码是由达芬奇软件生成的,那么这些代码的质量就会受到质疑。 【参考方案1】:

Q1:p3 是一个const 指针(意味着指针本身可能无法更改)到const struct s2 意味着struct s2 也无法更改。

Q2:*(&amp;p3-&gt;p1) 获取struct p3 的成员p1 的地址,然后取消引用它。使用该宏定义,分配需要是:(untilp1())-&gt;v1 = v2;。见Operator Precedence。我的建议是将括号放在宏中。

Q3:“一般编码” - 我认为这需要一个单独的问题。它可能是基于意见的。

Demo

【讨论】:

建议应在宏定义#define untilp1() (*(&amp;p3-&gt;p1)) 中加上圆括号,而不是在其用法(untilp1()) 中加上圆括号。这是避免错误的标准做法。 OP 说包含它的文件是由 DaVinci 生成的,但应该检查它是否可以更改。 @EricPostpischil 哦,我以为宏是给 OP 的,然后他错误地使用了它。更新了答案。

以上是关于难以理解表达式 (*(&x->y))的主要内容,如果未能解决你的问题,请参考以下文章

需要帮助理解 if 语句中的以下布尔表达式

列表理解不会在 Haskell 中给出正确的结果

有关JAVA里if判断语句中 如果只为一个& 怎么理解?

为啥 'typeid(x) == typeid(y)' 评估为真,其中 'x' 和 'y' 分别是 T 和 T& 类型的 id 表达式?

csapp datalab

csapp datalab