这种结构体用作链表的头:
struct lista
{
struct lista* next;
struct lista* prev;
};
如果next和prev都指向struct本身,则列表为空。以下宏可用于初始化该结构:
#define LISTA_INIT_EMPTY(list) { .next = (list), .prev = (list) }
:
struct lista my_list = LISTA_INIT_EMPTY(&my_list);
但是,有没有办法通过下面的方式做同样的事情,没有宏参数?:
struct lista my_list = LISTA_INIT_EMPTY;
我尝试了以下操作,但它导致编译错误:
#define LISTA_INIT_EMPTY { .next = &.next, .prev = &.next }
好吧,我看到的唯一的方式是不愉快的:
#define LISTA_INIT_EMPTY { .next = (&my_list), .prev = (&my_list) }
一点也不好,因为它只有在变量名为my_list
时才有效。没有好的方法,因为c中不存在this
为什么不使用NULL
而不是指向"this"?如果这还不能令人满意,保留参数化宏可能是最好的方法。
编辑:(感谢R在下面的评论,我终于明白了需要):
由于没有"this",并且只输入一次变量名,我建议使用这样的宏:
#define CREATE_EMPTY_LISTA(name) struct lista name = { .next=&name, .prev=&name }
后面的代码:
CREATE_EMPTY_LISTA(my_list); // creates and initializez my_list at the same time
注意,您的列表初始化技术与Linux内核源代码中用于链表(include/linux/list.h
)的技术类似。
在声明列表头时初始化列表,而不是尝试这样做:
// won't work:
struct lista my_list = /* something or other */;
Linux使用一个宏来执行声明和初始化(因此用户仍然只需要使用一次名称)。对于struct lista
,它可能看起来像:
#define LISTA_HEAD struct lista name = LISTA_INIT_EMPTY(name)
// this is all the user needs to do to both declare and initialize a list:
LISTA_HEAD(my_list);
看看include/linux/list.h
的所有细节。对于列表操作是如何工作的也有很好的解释(不是所有的都是直观的):
- Linux Kernel Development, Chapter 11.5, "Linked Lists"
- Linux内核链表解释
不尽然!如果你将empty定义为NULL而不是"本身"那么你可以这样做:
#define LISTA_INIT_EMPTY {NULL,NULL}
显然这是不可能的,因为块需要知道实例。
.next = &.next
也不能工作,因为类型不匹配。(struct lista*
to struct lista**
)
不,您的初始化器创建了一个struct lista
,然后将my_list
分配给它。你的this
的想法在这种情况下没有意义,它不会指向my_list
,直到它被分配。