Question

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, then 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 }
Was it helpful?

Solution

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

OTHER TIPS

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):

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top