如果有指向该结构成员的指针,是否有可移植方法来获取指向结构的指针?
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
有没有办法实现这个宏的可移植实现?