通过指向其成员的指针获取指向struct的指针

时间:2018-05-30 15:19:18

标签: c pointers

如果有指向该结构成员的指针,是否有可移植方法来获取指向结构的指针?

Linux内核(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)

这个想法是这个实现是通用的。您可以将其与任何struct类型一起使用:

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"
}

list_head的元素彼此链接,但只有指向list_head的指针,并且没有指向my_struct的指针(内部包含list_head)。但是,如果指向node的{​​{1}}成员,则可以使用my_struct宏将此指针转换为指向my_struct的指针。这是使用棘手的指针算法完成的(结构中成员的偏移量从成员的地址中减去)。

但是list_entry宏的实现是不可移植的,因为它使用 gcc 扩展和空指针的引用(通常是UB):

container_of

有没有办法实现这个宏的可移植实现?

0 个答案:

没有答案