offsetof、container_of、LinuxList

offsetof、container_of

功能介绍及使用注意事项:

/*功能:计算TYPE类中MEMBER成员的偏移量*/
#ifndef offsetof
#define offsetof(TYPE, MEMBER)	((unsigned int) &((TYPE *)0)->MEMBER)
#endif


/*
功能:将类里面的成员指针转为类指针
可以进行类型有效性检测,不是同一个类的会提示错误
( { } ) 与逗号表达式类似,结果为最后一个语句的值
注意事项:需要typeof关键字,gnuc是支持的,其他没支持的都无法使用该宏
参数1:当前成员地址 2:类(结构体)类型(父) 3:当前成员名
*/
#ifndef container_of
#define container_of(ptr,type,member)	\
    ({	const typeof(((type*)0)->member)* __mptr = (ptr);	\
        (type*)((char*)__mptr - offsetof(type,member));		\
    });
#endif

/*
与container_of功能相同,没有typeof关键字,所有编译器都可以使用
但没有类型检测(所有编译器都可以用),使用时要注意两个类型是是同一个类
*/
#ifndef container_of_new
#define container_of_new(ptr,type,member)	(type*)((char*)ptr - offsetof(type,member))
#endif

LinuxList

  Linux内核链表的数据定义
    -带头结点的双向循环链表,且头结点为表中成员
    -头结点的next指针指向首结点
    -头节点的prev指针指向尾结点

struct list_head {
    struct list_head *next, *prev;
};

使用Linux内核中的链表需要自己添加数据,定义结点
下面是其中常用的一些链表操作
注意使用container_of辅助使用

#define prefetch(x) ((void)x)//gnu c里面加速运行速度的,其他编译器没有,所以取消

#define LIST_POISON1  (NULL)//删除后的节点前继指向位置
#define LIST_POISON2  (NULL)//删除后的节点后驱指向位置

//初始化首结点
static void INIT_LIST_HEAD(struct list_head *list)
{
    list->next = list;
    list->prev = list;
}

//在prev与next之间添加结点
static void __list_add(struct list_head *node,
                  struct list_head *prev,
                  struct list_head *next)
{
    next->prev = node;
    node->next = next;
    node->prev = prev;
    prev->next = node;
}

//封装,在首结点后加入结点
static void list_add(struct list_head *node, struct list_head *head)
{
    __list_add(node, head, head->next);
}

//封装,在首结点前加入结点
static void list_add_tail(struct list_head *node, struct list_head *head)
{
    __list_add(node, head->prev, head);
}

//删除prev与next之间的结点,原对象还处在,不在链表里
static void __list_del(struct list_head * prev, struct list_head * next)
{
    next->prev = prev;
    prev->next = next;
}

//正序遍历
#define __list_for_each(pos, head) \
    for (pos = (head)->next; pos != (head); pos = pos->next)

//逆序遍历
#define list_for_each_prev(pos, head) \
    for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
            pos = pos->prev)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值