这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » 经典C语言指针问题关于list_entry

共1条 1/1 1 跳转至

经典C语言指针问题关于list_entry

助工
2014-11-26 20:12:29     打赏
关 于list_entry的问题 
#define list_entry(ptr, type, member) \
        ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
我不清楚的是(type *)0中的0代表的是什么啊?

问题补充:

在0这个地址看做有一个虚拟的type类型的变量,那么取一个成员再取这个成员的地址,就是这个结构体中这个成员的绝对地址                    这句话还是不明白,麻烦你在详细解释一下?




< type=text/java>
ik.qb.data.add('page','fromWap','0');




2008-10-3 17:27 最佳答案

你应该是在Linux源代码中看到的吧,这句话的意思是获取一个结构体中一个成员在这个结构体中的偏移。type *0是为了计算地址方便。意思是在0这个地址看做有一个虚拟的type类型的变量,那么取一个成员再取这个成员的地址,就是这个结构体中这个成员的绝对地址,由于结构体在地址为0的地方,所以这个成员在这个结构体中的相对位置也是这个值了。前面的ptr-...就要和你看到的代码具体联系了。我猜测ptr可能是这个member的指针,而现在想找这个member所在结构体的地址,所以这个member的地址应该减去这个member在这个结构体中的偏移。然后返回这个结构体类型。希望你明白了以上的种种,在你明白的同时希望你能感受到gnu那帮人写c的高超之处,哈哈!~

补充:意思就是:据个例子吧,

typedef struct

{

int i;

int j;

}exp;

这个exp结构体占用8个字节,假设声明一个变量。

exp e1;

那么假如已知e1.j的地址,想知道e1的地址该如何办呢?只要知道j在e1中的偏移,然后把j的地址减去这个偏移就是e1的地址了。在这里,i占据的前4个字节,所以j占据了5-8的字节。现在我们用你给出的list_entry来解释一下。

int *p = e1.j;

假设e1的地址是0x100,那么p就是0x104。可是如何才能比较方便的知道p减去4就是e1的地址呢?尤其是我们可能有时候不知道exp这个结构体里面具体什么样子的。下面的

list_entry(p, exp, j);

变成:

(exp *)((char *)p-(unsigned long)(&((exp *)0)->j)) 

(exp *)0在0地址上面建立8个字节的exp结构体,->j取出这个0地址上exp结构体里的j成员,&((exp *)0)->j)把这个成员地址取出来,由于j在这个结构体里是在5-8字节,所以从0地址数5个字节就是j所在的位置。这种方法省去了我们需要预先知道结构体具体什么样子,结构体里成员的位置怎么安排的。p的地址再减去我们刚算出来j所在的位置,就得到e1的地址。

也就是:

&e1 == list_entry(p, exp, j)

如果你还是有些困惑你需要找一些C的详细介绍的书籍,查看结构体一章中结构体在内存中的安排情况。

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]