Prashanth Chandra Prashanth Chandra - 1 month ago 4
C Question

Accessing struct member of pointer's address in C

I'm reading this book, and I found this code snippet in Chapter 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;
}


I understand that this dereferences p, a cdev pointer then accesses its owner member

p->owner // (*p).owner


However, how does this work? It seems like it dereferences the memory address of a cdev pointer then access the kobj member of the pointer itself?

&p->kobj // (*(&p)).kobj


I thought pointers weren't much more than memory addresses so I don't understand how they can have members. And if it was trying to access a member of the pointer itself, why not just do
p.kobj
?

Answer

As per p being defined as struct cdev *p, p is very much a "memory address" but it also has a type attached to it.

Since the expression *ptr means "the object pointed to by ptr", that also has the type attached, so you can logically do (*ptr).member.

And, since ptr->member is identical to (*ptr).member, it too is valid.

Bottom line is, your contention that "pointers [aren't] much more than memory addresses" is correct. But they are a little bit more :-)


In terms of &ptr->member, do not read that as (&ptr)->member.

Instead, as per C precedence rules, it is actually &(ptr->member), which means the address of the member of that structure. And the actual member is not evaluated here, it's exactly the same as &x not actually evaluating x, instead simply giving its address.

These precedence rules are actually specified by the ISO C standard (C11 in this case). From 6.5 Expressions, footnote 85:

The syntax specifies the precedence of operators in the evaluation of an expression, which is the same as the order of the major subclauses of this subclause, highest precedence first.

And, since 6.5.2 Postfix operators (the bit covering ->) comes before 6.5.3 Unary operators (the bit covering &), that means -> evaluates first.

Comments