难以理解表达式 (*(&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。具体来说,我不明白 (*(&p3->p2))
发生了什么。我知道#define
的含义。请详细解释一下表达式。
Q3 - 在一般编码中,我分配内存,例如在我声明使用指针之前使用malloc
。当这些文件由达芬奇生成时,我不确定这是如何处理的。但是我没有看到我的任何同事使用 malloc 等。有谁知道我是否可以使用p3
或untilp1()
将v2
的值分配给v1
?
谢谢。
【问题讨论】:
Expr 1
表示p3
是一个指向const struct s2
的const
指针。阅读更多here。
你可能会觉得这个网站很有趣:cdecl
Expr 2
将用*(&p3->p1)->v1
替换行untilp1()->v1 = v2;
。
*(&p3->p1)
只是写 (p3->p1)
的一种混淆方式。编写此类代码的唯一原因是程序员不知道运算符的优先级。这个代码库似乎有很大的代码味道。
(c) #define untilp1() *(&p3->p1)
是一个设计糟糕的定义,原因有两个。一,*(&p3->p1)
等价于p3->p1
,显然没有理由使用前一种形式。第二,众所周知,在宏中使用括号是一种很好的做法,如在#define untilp1() (*(&p3->p1))
中,以避免使用宏的优先级问题,这就是在untilp1()->v1 = v2;
中发生的导致错误的问题。 (->
的优先级高于*
,因此被解析为*((&p3->p1)->v1)
。)如果该代码是由达芬奇软件生成的,那么这些代码的质量就会受到质疑。
【参考方案1】:
Q1:p3
是一个const
指针(意味着指针本身可能无法更改)到const struct s2
意味着struct s2
也无法更改。
Q2:*(&p3->p1)
获取struct p3
的成员p1
的地址,然后取消引用它。使用该宏定义,分配需要是:(untilp1())->v1 = v2;
。见Operator Precedence。我的建议是将括号放在宏中。
Q3:“一般编码” - 我认为这需要一个单独的问题。它可能是基于意见的。
Demo
【讨论】:
建议应在宏定义#define untilp1() (*(&p3->p1))
中加上圆括号,而不是在其用法(untilp1())
中加上圆括号。这是避免错误的标准做法。 OP 说包含它的文件是由 DaVinci 生成的,但应该检查它是否可以更改。
@EricPostpischil 哦,我以为宏是给 OP 的,然后他错误地使用了它。更新了答案。以上是关于难以理解表达式 (*(&x->y))的主要内容,如果未能解决你的问题,请参考以下文章
为啥 'typeid(x) == typeid(y)' 评估为真,其中 'x' 和 'y' 分别是 T 和 T& 类型的 id 表达式?