About this blog

Save duplicate questions from disappearing from Google

Get pointer to struct by pointer to its member

Question

Is there a portable way to get a pointer to a structure if you have a pointer to a member of that structure?

There is a linked list implementation in Linux kernel (1):

struct list_head {
    struct list_head *next, *prev;
};

static inline void __list_add(struct list_head *new,
                  struct list_head *prev,
                  struct list_head *next)
{
    next->prev = new;
    new->next = next;
    new->prev = prev;
    prev->next = new;
}

static inline void list_add(struct list_head *new, struct list_head *head)
{
     __list_add(new, head, head->next);
}

#define list_entry(ptr, type, member) \
    container_of(ptr, type, member)

The idea is that this implementation is generic. You can use it with any struct type:

struct my_struct {
    int my_data;

    struct list_head node;
};

void example()
{
    struct list_head head;
    struct my_struct element1 = { 1 };
    struct my_struct element2 = { 2 };

    head.next = head.prev = &head;   // head <-> head
    list_add(&element1.node, &head); // head <-> {1} <-> head
    list_add(&element2.node, &head); // head <-> {2} <-> {1} <-> head

    struct my_struct *front_element = list_entry(&head.next, struct my_struct, node);

    printf("front element data: %d\n", front_element->my_data); // will print "2"
}

Elements of list_head are linked with each other, but there are only pointers to list_head and there are no pointers to my_struct (that contains list_head inside). However having a pointer to the node member of my_struct, you can convert this pointer to a pointer to my_struct itself using the list_entry macro. This is done using tricky pointer arithmetic (the offset of the member in the struct is subtracted from the address of the member).

But the implementation of the container_of macro is not portable because it uses gcc extensions and deferencing of null pointer (which is generally UB):

#define container_of(ptr, type, member) ({            \
    const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
    (type *)( (char *)__mptr - offsetof(type,member) );})

Is there a way to make a portable implementation of this macro?

Answer

Use offsetof macro that comes with compiler (not UB).

#define container_of(ptr, type, member) \
                      ((type *) ((char *)(ptr) - offsetof(type, member)))

That looks clean to me. It's only spread across > two lines for SO.