Chinaunix首页 | 论坛 | 博客
  • 博客访问: 161296
  • 博文数量: 34
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 317
  • 用 户 组: 普通用户
  • 注册时间: 2014-04-04 12:49
个人简介

专注于服务器开发技术

文章分类

全部博文(34)

文章存档

2015年(5)

2014年(29)

我的朋友

分类: LINUX

2014-08-04 17:10:57

list_head是linux内核中双向循环链表的经典实现。它在内核中的定义如下:
struct list_head {
struct list_head *next, *prev;
};
typedef struct list_head list_t;
list_head没有数据域,用于嵌套在其它结构中,可实现栈和队列。如:
typedef struct stu_t
{
    uint16_t stu_no;
    char stu_name[100];
    list_t list;
}stu;
此时list_t(即list_head)嵌套作为它的父结构的一个成员。
1.初始化 
#define INIT_LIST_HEAD(ptr) do { \
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)
初始化将head的next和prev都指向自己即可。初始化中的宏替换用do ..while(0)而不是{ ...}的原因如下:
(1).空语句在编译时候会出现警告;
(2).为了能够在里面定义局部变量;
(3).为了能够在条件语句中使用复杂的宏定义. 例如下面这段代码:
 #define FOO(x) \

  printf("arg is %s\n", x); \

  do_something_useful(x);

  如果这样用:

  if (blah == 2)

  FOO(blah);

  将会被展开为:

  if (blah == 2)

  printf("arg is %s\n", blah);

  do_something_useful(blah);;

  这样,if条件之包含了printf()语句,而 do_something_useful()调用不能按期望那样工作。而使用 do { ... } while(0)定义后,就会展开成以下语句:

  if (blah == 2)

  do {

  printf("arg is %s\n", blah);

  do_something_useful(blah);

  } while (0);

(4) 如果你希望定义一个包含多行语句和一些局部变量的时候. 一般的定义方式只能这样:

  #define exch(x,y) { int tmp; tmp=x; x=y; y=tmp; }

  然而在某些情况下,这样并不能正常工作. 下面是包含两个分支的if语句:

  if (x > y)

  exch(x,y);          // Branch 1

  else

  do_something();     // Branch 2

  但这样却只能展开成单分支的if语句,如下:

  if (x > y) {                // 单分支if

  int tmp;

  tmp = x;

  x = y;

  y = tmp;

  }

  ;                           // 空语句

  else                        // 错误!!! "parse error before else"

  do_something();

  问题是由于在语句块后直接加入分号(;)引起的. 解决办法是将语句块放入 do 和 while (0)中间.这样就得到了一条单语句, 而不是被编译器判断为语句块.现在的if语句如下:

  if (x > y)

  do {

  int tmp;

  tmp = x;

  x = y;

  y = tmp;

  } while(0);

  else

  do_something();


原文:

There are a couple of reasons:

  • (from Dave Miller) Empty statements give a warning from the compiler so this is why you see #define FOO do { } while(0).

  • (from Dave Miller) It gives you a basic block in which to declare local variables.

  • (from Ben Collins) It allows you to use more complex macros in conditional code. Imagine a macro of several lines of code like:

    #define FOO(x) /  printf("arg is %s/n", x); /  do_something_useful(x); 

    Now imagine using it like:

    if (blah == 2)  FOO(blah); 

    This interprets to:

    if (blah == 2)  printf("arg is %s/n", blah);  do_something_useful(blah);; 

    As you can see, the if then only encompasses the printf(), and the do_something_useful() call is unconditional (not within the scope of the if), like you wanted it. So, by using a block likedo { ... } while(0), you would get this:

    if (blah == 2)  do {  printf("arg is %s/n", blah);  do_something_useful(blah);  } while (0); 

    Which is exactly what you want.

  • (from Per Persson) As both Miller and Collins point out, you want a block statement so you can have several lines of code and declare local variables. But then the natural thing would be to just use for example:

    #define exch(x,y) { int tmp; tmp=x; x=y; y=tmp; } 

    However that wouldn't work in some cases. The following code is meant to be an if-statement with two branches:

    if (x > y)  exch(x,y);          // Branch 1 else  do_something();     // Branch 2 

    But it would be interpreted as an if-statement with only one branch:

    if (x > y) {                // Single-branch if-statement!!!  int tmp;            // The one and only branch consists  tmp = x;            // of the block.  x = y;  y = tmp; } ;                           // empty statement else                        // ERROR!!! "parse error before else"  do_something(); 

    The problem is the semi-colon (;) coming directly after the block. The solution for this is to sandwich the block between do and while (0). Then we have a single statement with the capabilities of a block, but not considered as being a block statement by the compiler. Our if-statement now becomes:

    if (x > y)  do {  int tmp;  tmp = x;  x = y;  y = tmp;  } while(0); else  do_something();
2.添加节点
    2.1 入栈
        /**
         * list_add - add a new entry
         * @new: new entry to be added
         * @head: list head to add it after
         *
         * Insert a new entry after the specified head.
         * This is good for implementing stacks.
         */
    static inline void list_add(list_t *new, list_t *head)
 2.2 入队列
    /**
        * list_add_tail - add a new entry
        * @new: new entry to be added
      * @head: list head to add it before
   *
       * Insert a new entry before the specified head.
     * This is useful for implementing queues.
     */
    static inline void list_add_tail(list_t *new, list_t *head)

3.删除节点
/**
 * list_del - deletes entry from list.
 * @entry: the element to delete from the list.
 * Note: list_empty on entry does not return true after this, the entry is in an undefined state.
 */
static inline void list_del(list_t *entry)
4.删除节点并初始化
/**
 * list_del_init - deletes entry from list and reinitialize it.
 * @entry: the element to delete from the list.
 */
static inline void list_del_init(list_t *entry)
5.从A链表中删除一个节点,并将它添加B链表头部
/**
 * list_move - delete from one list and add as another's head
 * @list: the entry to move
 * @head: the head that will precede our entry
 */
static inline void list_move(list_t *list, list_t *head)
5.从A链表中删除一个节点,并将它添加B链表尾部
/**
 * list_move_tail - delete from one list and add as another's tail
 * @list: the entry to move
 * @head: the head that will follow our entry
 */
static inline void list_move_tail(list_t *list, list_t *head)
7.测试链表是否为空
/**
 * list_empty - tests whether a list is empty
 * @head: the list to test.
 */
static inline int list_empty(list_t *head)
8.合并两个链表为一个链表
/**
 * list_splice - join two lists
 * @list: the new list to add.
 * @head: the place to add it in the first list.
 */
static inline void list_splice(list_t *list, list_t *head)
9.合并两个链表为一个链表,并初始化为空表
/**
 * list_splice_init - join two lists and reinitialise the emptied list.
 * @list: the new list to add.

 * @head: the place to add it in the first list.
 *
 * The list at @list is reinitialised
 */
static inline void list_splice_init(list_t *list, list_t *head)

10.取链表中某个条目(entry)
/**
 * list_entry - get the struct for this entry
 * @ptr: the &list_t pointer.[list_head 结构指针]
 * @type: the type of the struct this is embedded in.[嵌套结构类型]
 * @member: the name of the list_struct within the struct.[嵌套结构中list_head 成员变量名]
 */
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))

11.遍历链表
/**
 * list_for_each - iterate over a list
 * @pos: the &list_t to use as a loop counter.
 * @head: the head for your list.
 */
#define list_for_each(pos, head) \
for (pos = (head)->next ; pos != (head); pos = pos->next )


阅读(1286) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~