user/include/linux/list.h
这个声明:
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr) – (unsigned long)(&((type *)0)->member)))
有人可以解释这是什么以及如何运作,提前谢谢
P.S。请尽可能地简化你的答案,我知道Linux中的线程,进程,现在我正在探索可能性,而且我对这个有点困惑。
答案 0 :(得分:29)
考虑两个这样的结构:
struct data {
int something;
};
struct container {
int something_before;
struct data data_item;
int something_after;
};
假设您有一个指向struct data
值的指针:
struct data *data_ptr;
list_entry()
宏可帮助您将data_ptr
转换为指向struct container
值的指针,该值包含struct data
指向的值ptr
:< / p>
struct container *cont_ptr = list_entry(data_ptr, struct container, data_item);
宏通过计算data_item
内struct container
的偏移量,并从data_ptr
指针中减去那么多字节来工作。当转换为struct container *
时,这会向struct container
提供一个有效指针,该指针将struct data
“置于”内部“。
使用内置offsetof()
宏:
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr) – offsetof(type, member)))
答案 1 :(得分:10)
答案 2 :(得分:2)
此宏用于查找给定其成员之一的结构的地址。
因此,例如,假设你有结构:
typedef struct
{
int i;
int j;
} typestruct;
你需要知道的第一件事是宏的最后一部分:
&((typestruct *)0)->j
用于给出成员的偏移量。因此,它是从类型的零内存到成员的大小(以字节为单位)。在这种情况下,它是sizeof(int)
,因为j
正好是int i
;因此,为简单起见,我们假设此表达式值为4
。您可以使用宏
offsetof(typestruct, j);
现在我们想要计算temp
的地址,其中temp
是typestruct temp
。为此,我们简单地计算指针的地址减去成员位置。指针的地址是:
(typestruct *)((char *) &temp.j)
因此,减法是:
&temp == (typestruct *)((char *) &temp.j) - offsetof(typestruct, j)
或者像宏说的那样:
&temp == (typestruct *)((char *) &temp.j) - &((typestruct *)0)->j
(括号是必要的,但为了澄清而被删除)