Is it possible to get a pointer to the 'this' structure when using a designated initializer?

This type of structure is used as the head of a linked list:

struct lista { struct lista* next; struct lista* prev; }; 

When next and prev both indicate their own structure, the list is empty. The following macro can be used to initialize the structure:

 #define LISTA_INIT_EMPTY(list) { .next = (list), .prev = (list) } 

in the following way:

 struct lista my_list = LISTA_INIT_EMPTY(&my_list); 

But is there a way to do the same as follows, without the macro parameter ?:

 struct lista my_list = LISTA_INIT_EMPTY; 

I tried the following, but this caused a compilation error:

 #define LISTA_INIT_EMPTY { .next = &.next, .prev = &.next } 
+6
source share
5 answers

Well, the only way I see is unpleasant:

 #define LISTA_INIT_EMPTY { .next = (&my_list), .prev = (&my_list) } 

I do not like it at all, since it only works if your variable is called my_list . And there is nothing good, since this does not exist in C.

Why not use NULL instead of pointing to "this"? If this is not satisfactory, saving a parameterized macro is probably the best.

EDIT: (thanks R comment below, I finally understood the need):

Since there is no β€œthis” and only enter the variable name once, I suggest using a macro like this:

 #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 
+6
source

Note that your list initialization method is similar to that used in the Linux kernel source for linked lists ( include/linux/list.h ).

To initialize a list when declaring a list title, instead of trying to do something like:

 // won't work: struct lista my_list = /* something or other */; 

Linux uses a macro that performs both division and initialization (therefore, the user should still use this name only once). For your struct lista this might look like this:

 #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 good explanations of how operation lists work (not all of this is intuitive):

+2
source

Not really! If you define empty as NULL instead of "yourself", you can do this with:

#define LISTA_INIT_EMPTY {NULL,NULL}

0
source

Apparently this is not possible, since the block must know the instance.

Also .next = &.next will not work as the types do not match. ( struct lista* before struct lista** )

0
source

No, your initializer creates a struct lista and then assigns it my_list . Your idea of this does not make sense in this context, it will not indicate my_list until then, until it is assigned.

0
source

Source: https://habr.com/ru/post/895679/


All Articles