dhilst

container_of


/*
* This example show how get sibling members of a struct. Suppose that you
* have a struct foo with members A and B. With the macros provided here you can
* get the address of B, having a pointer to A and knowing that B is the B member
* of struct foo. This is not my work, is just based on macros provided by gcc
* compiler __builtin_offsetof() and the container_of() macro found on linux
* kernel sources.
*/
#include <stdio.h>

/*
* You can get the offset of a member on a struct by dereferencing that member on
* address 0 of such structure.
*/
#define offset_of(type, member) ((unsigned long) &((type *)0)->member)

/*
* With the capability to get offsets, is possible to get the address of the
* struct that contains some data. We just need a pointer to that data and the
* offset of that data on the struct. With this informations we can calculate
* the address of struct by subtracting the offset from the pointer to that data
* contained on struct. In the macro above the @ptr is the data contained on
* struct.
*/
#define container_of(ptr, type, member) \
((type *) ((char *)ptr - offset_of(type, member)))

struct foo {
char *str;
int len;
};

void print_sibling(int *ip);

int main(void)
{
struct foo bar = {
.str = "Hello World",
.len= 11,
};
print_sibling(&bar.len);

return 0;

}

/*
* This function receives an int pointer (@ip) that is known to be the member "len" of
* a "struct foo". With such information we can do the magic and take any
* "sibling" member of that struct.
*/
void print_sibling(int *ip)
{
struct foo *tmp = container_of(ip, struct foo, len);
puts(tmp->str);
}