Is it possible to get pointer to the 'this' structure, when using designated initializer?
This kind of struct is used as head of linked list:
struct lista
{
struct lista* next;
struct lista* prev;
};
When next and prev both points to struct itself, th开发者_JS百科en the list is empty. The following macro can be used for initializing the structure:
#define LISTA_INIT_EMPTY(list) { .next = (list), .prev = (list) }
this way:
struct lista my_list = LISTA_INIT_EMPTY(&my_list);
But, is there any way to do same thing by the following way, without macro parameter?:
struct lista my_list = LISTA_INIT_EMPTY;
I tried the following, but it caused a compile error:
#define LISTA_INIT_EMPTY { .next = &.next, .prev = &.next }
Well, the only way I see is unpleasant:
#define LISTA_INIT_EMPTY { .next = (&my_list), .prev = (&my_list) }
Not nice at all as it only works if your variable is called my_list
. And there's no nice way as this
does not exist in C.
Why not using NULL
instead of pointing to "this"? If this is not satisfactory, keeping the parameterized macro is probably the best.
EDIT: (thanks to R's comment below, I finally understood the need):
As there no "this" and to only enter the name of the variable once, I suggest using such a macro:
#define CREATE_EMPTY_LISTA(name) struct lista name = { .next=&name, .prev=&name }
And later in the code:
CREATE_EMPTY_LISTA(my_list); // creates and initializez my_list at the same time
Note that your list initialization technique is similar what's used in the Linux kernel source for their linked lists (include/linux/list.h
).
For initialization of a list when the list head is declared, instead of trying to do something like:
// won't work:
struct lista my_list = /* something or other */;
Linux uses a macro that performs both the delcaration and the initialization (so the user still has to use the name only once). For your struct lista
it might look like:
#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);
Take a look at include/linux/list.h
for all the details. There are also nice explanations of how the lists operations work (not all of it is intuitive):
- Linux Kernel Development, Chapter 11.5, "Linked Lists"
- Linux Kernel Linked List Explained by Kulesh Shanmugasundaram
Not really! If you define empty as NULL instead of "itself" then you could do it by:
#define LISTA_INIT_EMPTY {NULL,NULL}
Apparently this is not possible, since the block needs to know the instance.
Also .next = &.next
will not work since the types do not match. (struct lista*
to struct lista**
)
No, your initializer creates a struct lista
and then assigns my_list
to it. Your idea of a this
does not make sense in this context, it wouldn't point to my_list
until after it had been assigned.
精彩评论