list.h 简单运用

http://blog.csdn.net/u012566181/article/details/38313227

#include <stdio.h>
 #include <stdlib.h>

#include "list.h"

struct kool_list
{
    struct list_head list;
    int to,from;
};
//这个定义把list_head结构放在第一位很有讲究,因为后面
//可以直接利用list_for_each宏来直接得到koo_list的位置,因为
//每个koo_list结构中,如果这样定义的化,那么list的地址和
//结构的地址就是一样的,那时,我们可以直接强制转换即可得到了。


/*int main(int ac,char **av)
{
    if(ac!=2)
	return 0;
    int n=atoi(av[1]);
    int i=0;

    struct kool_list mylist;
    //这定义了一个表头
    INIT_LIST_HEAD(&mylist.list);
    //初始化表头,注意传递的参数,是list成员的地址  .优先级比&高


    struct kool_list *tmp;
    struct list_head *pos;

    for(i=0;i<n;i++)
    {
	tmp=(struct kool_list*)malloc(sizeof(struct kool_list));

	printf("intput to and from:");
	scanf("%d %d",&tmp->to,&tmp->from);

	list_add(&tmp->list,&mylist.list);
	//像这种对链表的操作,基本伤都是对list的操作,
	//所以,传参进去时候要传递成员list的地址。
    }

    list_for_each(pos,&mylist.list)
    {
	//这时候,pos是某个struct kool_list结构的list的地址
	//所以在通常情况下,需要进行从list找相应的主体结构。
	tmp=list_entry(pos,struct kool_list,list);
	//这样,tmp现在为pos相应的主体结构struct kool_list的地址了.
	printf("%d---%d\n",tmp->to, tmp->from);

	//前面说到,因为list是定义的第一个成员,所以,我们也可页这样
	//得到主体的结构.
	tmp=(struct kool_list*)pos;
	printf("%d---%d\n",tmp->to,tmp->from);
    }


    return 0;
} */


/*在运用list_head的时候,关键是要区分list_head的成员与其主体的关系
不要忘记了。 */












/*很多初学者对于从pos是怎样得到主体的地址的不明白,
//即对与宏list_entry的实现不是很清楚,下面来解释一下.
//毕竟不是每个结构都会把list放在开头的,清楚这个宏
//有一定的好处。
*/

#define list_entry(ptr,type,member)\
    ((type*)((char*)(ptr)-(unsigned long)(&((type*)0)->member)))

//傻眼了....
//按照上面的例子展开就是

    ((struct kool_list*)((char*)(pos)-(unsigned long)(&((struct kool_list*)0)->list)));

//下面解释一下
//如果我们要对某个结构中的成员,求出该成员相对于结构首地址的偏移,那么我们应该怎么做

//假如有这样的结构;
struct foo_bar
{
    ....
    int boo;
    ....
};
//我们要得到boo的偏移,那么这样
(unsigned long )(&((struct foo_bar*)0)->boo);

//是不是简单多了。既然我们得到了boo的偏移,那么计算foo_bar的地址就用bar的地址减去boo的偏移
//即可,(注意,地址是向下增加的)
//
//为了对以上有个感性的认识,那么看个小程序段落. 
struct foobar{
    unsigned int foo;
    char bar;
    char boo;
};
int main(int ac,char**av)
{
    struct foobar tmp;

    printf("address of tmp is=%p\n\n",&tmp);
    printf("address of tmp->foo %p \t offset of foo=%lu\n",
	    &tmp.foo,(unsigned long ) &((struct foobar*)0)->foo);

    printf("address of tmp->bar %p \t offset of bar=%lu\n",
	    &tmp.bar,(unsigned long ) &((struct foobar*)0)->bar);

    printf("address of tmp->boo %p \t offset of boo=%lu\n",
	    &tmp.boo,(unsigned long ) &((struct foobar*)0)->boo);


    printf("computed address of &tmp using:\n");

    //printf("\t address and offset  of tmp->foo=%p\n",
//	    (struct foobar*)(((char*)&tmp.foo)-((unsigned long )&((struct foobar*)0->foo))));

    return 0;
}



















  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值