list.h头文件分析

现在开始:


  1. structlist_head {
  2.        struct list_head *next, *prev; 
  3. };

这个就是那个链表的头!是不觉得很奇怪?怎么只有两个指针域,没有数据域呢?其实我现在也纠结这这个问题着呢!没事,咱们先往下看。说不定什么时候,咱就明白了这是怎么一回事情呢。


  1. #define LIST_HEAD_INIT(name) { &(name), &(name) }
  2. #defineLIST_HEAD(name) \
  3.        struct list_head name = LIST_HEAD_INIT(name)

这俩是宏没错吧!来看看这个俩到底是个什么意思。

先来看看这个LIST_HEAD_INIT(name),当程序当中出现了这个东西的时候,他立马就会替换成后面的东西,例如出现了:

LIST_HEAD_INIT(headnode)

他立马就会替换成{&(headnode),&(headnode)},有人会问这个到底是什么意思;呵呵不要着急!下面详细的说明:

假设有这么一段C代码

……….

 struct list_head headnode ;//定义了一个headnode节点

 headnode = LIST_HEAD_INIT(headnode);

……….

那么他是不应该再编译阶段就立马的被替换成这样呢?

……….

 struct list_head headnode ;//定义了一个headnode节点

 headnode = { &(headnode), &(headnode) };

……….

注意:这里面对标准的C进行了拓展叫:GNU C,这个意思呢就是说,对headnode的两个成员赋值。这赋值之后成了什么样子了呢?看下图:


是不是自己指向了自己?至于为什么可以这么赋值,不是本文讨论的重点,详细的可以www.baidu.com或者www.google.com.hk

 

其实这里的LIST_HEAD_INIT(name)宏是用来初始化的;

LIST_HEAD(name)宏则是用来定义+初始化。你看LIST_HEAD(name)宏是不比LIST_HEAD_INIT(name)宏多了这句 struct list_head name 

记住:LIST_HEAD_INIT(name)宏是用来初始化的;LIST_HEAD(name)宏则是用来定义+初始化。

 

 

OK,我们接着往下看:


  1. static inline void INIT_LIST_HEAD(struct list_head *list)
  2. {
  3.        list->next = list;
  4.        list->prev = list;
  5. }

奇怪这里怎么好像又是在初始化,而且还和上面的功能一样。我觉得,他们这样做有如下考虑:1、有些人习惯于调用函数进行初始化,而有的人喜欢代码简洁而直接使用宏来进行初始化,但是不论是那种方式,都达到了一样的功能-----初始化。

 

 

在往下看,有关链表添加的


  1. #ifndef CONFIG_DEBUG_LIST
  2. static inline void __list_add(struct list_head *new,
  3.                            struct list_head *prev,
  4.                            struct list_head *next)
  5. {
  6.        next->prev = new;
  7.        new->next = next;
  8.        new->prev = prev;
  9.        prev->next = new;
  10. }
  11. #else
  12. extern void __list_add(struct list_head *new,
  13.                            struct list_head *prev,
  14.                            struct list_head *next);

没有评论: