user/include/linux/list.h
this declaration:
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr) – (unsigned long)(&((type *)0)->member)))
can somebody please explain what is this and how does it work, th开发者_如何学Pythonanks in advance
P.S. please simplify your answer as much as possible, I know about threads, processes in Linux, now I'm exploring possibilities and I'm a little bit stuck with this one.
Consider two structs like this:
struct data {
int something;
};
struct container {
int something_before;
struct data data_item;
int something_after;
};
Assume you have a pointer to a struct data
value:
struct data *data_ptr;
The list_entry()
macro helps you to convert data_ptr
to a pointer to the struct container
value that holds the struct data
value, pointed to by ptr
:
struct container *cont_ptr = list_entry(data_ptr, struct container, data_item);
The macro works by computing the offset of data_item
inside the struct container
, and subtracting that many bytes from the data_ptr
pointer. This, when cast to struct container *
, gives a valid pointer to the struct container
that holds this particular struct data
"inside".
The macro can also be simplified a bit by using the builtin offsetof()
macro:
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr) – offsetof(type, member)))
An explanation of this you find here: Section How Does This Work?
This macro is used to find the address of a struct given one of its member.
So, for example, suppose you have the struct:
typedef struct
{
int i;
int j;
} typestruct;
First thing you need to know is that the last part of the macro:
&((typestruct *)0)->j
Is used to give the offset of a member. So, it is the size, in bytes, from the zero memory casted to the type, to the member. In this case, it is the sizeof(int)
, because j
is just bellow int i
; So lets assume this expression values 4
for simplicity. You can get the same result with the macro
offsetof(typestruct, j);
Now we want to calculate the address of temp
, where temp
is typestruct temp
. To do that, we simple compute the address of the pointer minus the member position. The address of the pointer is:
(typestruct *)((char *) &temp.j)
Hence, the subtraction is:
&temp == (typestruct *)((char *) &temp.j) - offsetof(typestruct, j)
or, like the macro says:
&temp == (typestruct *)((char *) &temp.j) - &((typestruct *)0)->j
You can learn much more here, and also in this question.
(Parenthesis are necessary, but was eliminated for clarification)
精彩评论