我正在阅读这本书,我在第 14 章中找到了这个代码片段。
struct kobject *cdev_get(struct cdev *p)
{
struct module *owner = p->owner;
struct kobject *kobj;
if (owner && !try_module_get(owner))
return NULL;
kobj = kobject_get(&p->kobj);
if (!kobj)
module_put(owner);
return kobj;
}
Run Code Online (Sandbox Code Playgroud)
我知道这会取消引用 p,然后一个 cdev 指针访问其所有者成员
p->owner // (*p).owner
Run Code Online (Sandbox Code Playgroud)
但是,这是如何工作的?似乎它取消引用 cdev 指针的内存地址然后访问指针本身的 kobj 成员?
&p->kobj // (*(&p)).kobj
Run Code Online (Sandbox Code Playgroud)
我认为指针不仅仅是内存地址,所以我不明白它们如何拥有成员。如果它试图访问指针本身的成员,为什么不直接做p.kobj?
根据p被定义为struct cdev *p,p很大程度上是一个“内存地址”,但这还不是全部——它还附加了一个类型。
由于表达式*ptr是“指向的对象ptr”,因此也附加了类型,因此您可以在逻辑上执行(*ptr).member.
并且,由于ptr->member与 相同(*ptr).member,所以它也是有效的。
最重要的是,您关于“指针 [不是]比内存地址多得多”的论点是正确的。但他们多一点:-)
就 而言&ptr->member,您似乎将其解读为(&ptr)->member,这是不正确的。
相反,根据 C 优先级规则,它实际上是&(ptr->member),这意味着该结构的成员的地址。
这些优先规则实际上是由 ISO C 标准(在本例中为 C11)指定的。来自6.5 Expressions,脚注85:
语法指定运算符在表达式求值中的优先级,与本小节的主要小节的顺序相同,最高优先级在前。
而且,由于6.5.2 Postfix operators(位覆盖->)在6.5.3 Unary operators(位覆盖&)之前,这意味着->首先评估。