Generally speaking, there are more elegant ways of doing this. One way I have seen is this:
Consider a structure like this:
struct mystruct {
member *a;
another_member b;
something *c;
...
};
So, if you have a pointer to c, to get a pointer to mystruct, you could do this:
mystruct *s = (mystruct *)(( (byte *)c - (byte *)((mystruct *)0)->c)
What this is doing is casting the address 0 to the type mystruct. Then, if you are pointing to the "c" member, that gives you the actual relative offset of "c" in the structure. All that remains is to subtract this offset from "c" itself, in order to get a pointer to the containing structure.
Linux kernel does something similar - the macro container_of provides this functionality:
#define offsetof(TYPE, MEMBER)
((size_t) &((TYPE *)0)->MEMBER)
/**
* container_of - cast a member of a structure out to the containing structure
* @ptr: the pointer to the member.
* @type: the type of the container struct this is embedded in.
* @member: the name of the member within the struct.
*
*/
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
It does the same thing if you ignore all the casting. It first gets a pointer to the member of a 0-based structure, and then subtracts the offset of the member from this address to get the base.
No comments:
Post a Comment