6

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 }
SKi
  • 8,007
  • 2
  • 26
  • 57

5 Answers5

6

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
Shlublu
  • 10,917
  • 4
  • 51
  • 70
  • 2
    I think OP wants all lists, including the initial empty one, to be circular. This is not entirely unreasonable; often it eliminates all the ugly corner cases in your list handling functions. – R.. GitHub STOP HELPING ICE Aug 23 '11 at 13:57
  • 1
    `CREATE_EMPTY_LISTA` is basically the same as `LISTA_INIT_EMPTY` mentioned by the OP. – Alok Singhal Aug 23 '11 at 14:14
  • 1
    Yes, but with one important difference: `struct lista my_list = LISTA_INIT_EMPTY(&my_list);` forces you to repeat the name of the variable, which is not nice and quite error prone. `CREATE_EMPTY_LISTA(my_list);` allows you not repeating it. – Shlublu Aug 23 '11 at 14:16
2

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

Michael Burr
  • 333,147
  • 50
  • 533
  • 760
0

Not really! If you define empty as NULL instead of "itself" then you could do it by:

#define LISTA_INIT_EMPTY {NULL,NULL}

noelicus
  • 14,468
  • 3
  • 92
  • 111
0

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

Constantinius
  • 34,183
  • 8
  • 77
  • 85
0

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.

τεκ
  • 2,994
  • 1
  • 16
  • 14