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 )
阅读(1347) | 评论(0) | 转发(0) |