* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*/
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
请问这个函数是什么意思,有什么功能?
请诸位分析一下(详细)
11 个解决方案
#1
<linux/list.h>中,请各位帮忙
感激不尽
感激不尽
#2
(&((type *)0)->member)表示取得结构type的成员member的偏移量。强制转换为(unsigned long)。
ptr减去上边算出的偏移量,然后将所得的地址强制转换为(type *)。
ptr减去上边算出的偏移量,然后将所得的地址强制转换为(type *)。
#3
那么这个宏是做什么用的呢?麻烦能举个例子说的详细一点嘛?
不胜感激
不胜感激
#4
顺便问一下 , 宏中的各个变量都是什么含义 ,我翻译的不是很透彻
谢谢各位了
谢谢各位了
#5
typedef struct A_
{
int a;
long l;
short s;
}A;
A a;
void* p = &a.l;
A* pa = list_entry(p, A, l); // 结构(实体)成员地址,结构(实体)类型定义,成员名
{
int a;
long l;
short s;
}A;
A a;
void* p = &a.l;
A* pa = list_entry(p, A, l); // 结构(实体)成员地址,结构(实体)类型定义,成员名
#6
这个是linux内核使用的一个通用双向链表结构的一部分。该链表结构是这样的:
struct list_head {
struct list_head *next, *prev;
};
例如要建立一个双向链表,可以这样:
struct cpufreq_governor {
char name[CPUFREQ_NAME_LEN];
int (*governor) (struct cpufreq_policy *policy,
unsigned int event);
struct list_head governor_list;
struct module *owner;
};
注意其中的governor_list,它是用来实现cpufreq_governor双向链表的关键:
cpufreq_governor governor;
list_add(&governor->governor_list, &cpufreq_governor_list);
其中cpufreq_governor_list是struct list_head类型,是整个链表的head。这样就用list_head这个双向链表将cpufreq_governor的成员governor_list链接了起来,也就是说从以cpufreq_governor_list为head的链表里能够访问到的是每个cpufreq_governor的成员变量governor_list。然而我们实际需要的是cpufreq_governor,即整个结构,于是就有了list_entry这个宏:将governor_list这个成员变量的地址减去它在结构中的偏移量就是结构的地址。
所以,ptr就是成员变量的地址(例子中的governor_list的地址),type是结构名(例子中的cpufreq_governor),member就是成员变量的名字(例子中的governor_list)。
struct list_head {
struct list_head *next, *prev;
};
例如要建立一个双向链表,可以这样:
struct cpufreq_governor {
char name[CPUFREQ_NAME_LEN];
int (*governor) (struct cpufreq_policy *policy,
unsigned int event);
struct list_head governor_list;
struct module *owner;
};
注意其中的governor_list,它是用来实现cpufreq_governor双向链表的关键:
cpufreq_governor governor;
list_add(&governor->governor_list, &cpufreq_governor_list);
其中cpufreq_governor_list是struct list_head类型,是整个链表的head。这样就用list_head这个双向链表将cpufreq_governor的成员governor_list链接了起来,也就是说从以cpufreq_governor_list为head的链表里能够访问到的是每个cpufreq_governor的成员变量governor_list。然而我们实际需要的是cpufreq_governor,即整个结构,于是就有了list_entry这个宏:将governor_list这个成员变量的地址减去它在结构中的偏移量就是结构的地址。
所以,ptr就是成员变量的地址(例子中的governor_list的地址),type是结构名(例子中的cpufreq_governor),member就是成员变量的名字(例子中的governor_list)。
#7
简单的举个例子:
有一个结构体
struct {
...
struct list_head next;
...
}StructType;
StructType MyStruct;
你用listentry( p , StructType, next )就得到了指向Mystruct的指针
下边是图示
->---------- MyStruct->---------------
| 。 。 | | 。。 |
+---------+ p->+--------------+
|list_head| <==> | list_head |
+---------+ +--------------+
| 。 。 | | 。。 |
+---------+ +--------------+
有一个结构体
struct {
...
struct list_head next;
...
}StructType;
StructType MyStruct;
你用listentry( p , StructType, next )就得到了指向Mystruct的指针
下边是图示
->---------- MyStruct->---------------
| 。 。 | | 。。 |
+---------+ p->+--------------+
|list_head| <==> | list_head |
+---------+ +--------------+
| 。 。 | | 。。 |
+---------+ +--------------+
#8
对阿 ,我当初分析的时候就就感到奇怪,为了将链表操作与特定数据分离,有两种方法,
linux中的这用方法是属于完全分离,与特定数据一点关系都没有,这样虽然可以通过链表
嵌入进行连接操作,但包含它的那个struct却不知如何如何定位!
终于明白了 谢谢各位
请继续讨论
linux中的这用方法是属于完全分离,与特定数据一点关系都没有,这样虽然可以通过链表
嵌入进行连接操作,但包含它的那个struct却不知如何如何定位!
终于明白了 谢谢各位
请继续讨论
#9
分析的很透彻啊,佩服各位。这些都是c中链表操作控制
#10
主要就是看懂 (&((type *)0)->member) 的意思。
#11
mark
cvsuser(猪头)
cvsuser(猪头)
#1
<linux/list.h>中,请各位帮忙
感激不尽
感激不尽
#2
(&((type *)0)->member)表示取得结构type的成员member的偏移量。强制转换为(unsigned long)。
ptr减去上边算出的偏移量,然后将所得的地址强制转换为(type *)。
ptr减去上边算出的偏移量,然后将所得的地址强制转换为(type *)。
#3
那么这个宏是做什么用的呢?麻烦能举个例子说的详细一点嘛?
不胜感激
不胜感激
#4
顺便问一下 , 宏中的各个变量都是什么含义 ,我翻译的不是很透彻
谢谢各位了
谢谢各位了
#5
typedef struct A_
{
int a;
long l;
short s;
}A;
A a;
void* p = &a.l;
A* pa = list_entry(p, A, l); // 结构(实体)成员地址,结构(实体)类型定义,成员名
{
int a;
long l;
short s;
}A;
A a;
void* p = &a.l;
A* pa = list_entry(p, A, l); // 结构(实体)成员地址,结构(实体)类型定义,成员名
#6
这个是linux内核使用的一个通用双向链表结构的一部分。该链表结构是这样的:
struct list_head {
struct list_head *next, *prev;
};
例如要建立一个双向链表,可以这样:
struct cpufreq_governor {
char name[CPUFREQ_NAME_LEN];
int (*governor) (struct cpufreq_policy *policy,
unsigned int event);
struct list_head governor_list;
struct module *owner;
};
注意其中的governor_list,它是用来实现cpufreq_governor双向链表的关键:
cpufreq_governor governor;
list_add(&governor->governor_list, &cpufreq_governor_list);
其中cpufreq_governor_list是struct list_head类型,是整个链表的head。这样就用list_head这个双向链表将cpufreq_governor的成员governor_list链接了起来,也就是说从以cpufreq_governor_list为head的链表里能够访问到的是每个cpufreq_governor的成员变量governor_list。然而我们实际需要的是cpufreq_governor,即整个结构,于是就有了list_entry这个宏:将governor_list这个成员变量的地址减去它在结构中的偏移量就是结构的地址。
所以,ptr就是成员变量的地址(例子中的governor_list的地址),type是结构名(例子中的cpufreq_governor),member就是成员变量的名字(例子中的governor_list)。
struct list_head {
struct list_head *next, *prev;
};
例如要建立一个双向链表,可以这样:
struct cpufreq_governor {
char name[CPUFREQ_NAME_LEN];
int (*governor) (struct cpufreq_policy *policy,
unsigned int event);
struct list_head governor_list;
struct module *owner;
};
注意其中的governor_list,它是用来实现cpufreq_governor双向链表的关键:
cpufreq_governor governor;
list_add(&governor->governor_list, &cpufreq_governor_list);
其中cpufreq_governor_list是struct list_head类型,是整个链表的head。这样就用list_head这个双向链表将cpufreq_governor的成员governor_list链接了起来,也就是说从以cpufreq_governor_list为head的链表里能够访问到的是每个cpufreq_governor的成员变量governor_list。然而我们实际需要的是cpufreq_governor,即整个结构,于是就有了list_entry这个宏:将governor_list这个成员变量的地址减去它在结构中的偏移量就是结构的地址。
所以,ptr就是成员变量的地址(例子中的governor_list的地址),type是结构名(例子中的cpufreq_governor),member就是成员变量的名字(例子中的governor_list)。
#7
简单的举个例子:
有一个结构体
struct {
...
struct list_head next;
...
}StructType;
StructType MyStruct;
你用listentry( p , StructType, next )就得到了指向Mystruct的指针
下边是图示
->---------- MyStruct->---------------
| 。 。 | | 。。 |
+---------+ p->+--------------+
|list_head| <==> | list_head |
+---------+ +--------------+
| 。 。 | | 。。 |
+---------+ +--------------+
有一个结构体
struct {
...
struct list_head next;
...
}StructType;
StructType MyStruct;
你用listentry( p , StructType, next )就得到了指向Mystruct的指针
下边是图示
->---------- MyStruct->---------------
| 。 。 | | 。。 |
+---------+ p->+--------------+
|list_head| <==> | list_head |
+---------+ +--------------+
| 。 。 | | 。。 |
+---------+ +--------------+
#8
对阿 ,我当初分析的时候就就感到奇怪,为了将链表操作与特定数据分离,有两种方法,
linux中的这用方法是属于完全分离,与特定数据一点关系都没有,这样虽然可以通过链表
嵌入进行连接操作,但包含它的那个struct却不知如何如何定位!
终于明白了 谢谢各位
请继续讨论
linux中的这用方法是属于完全分离,与特定数据一点关系都没有,这样虽然可以通过链表
嵌入进行连接操作,但包含它的那个struct却不知如何如何定位!
终于明白了 谢谢各位
请继续讨论
#9
分析的很透彻啊,佩服各位。这些都是c中链表操作控制
#10
主要就是看懂 (&((type *)0)->member) 的意思。
#11
mark
cvsuser(猪头)
cvsuser(猪头)