2011-08-23 7 views
6

Este tipo de estructura se utiliza como cabeza de lista enlazada:¿Es posible obtener un puntero a la estructura 'this' cuando se utiliza el inicializador designado?

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

Cuando next y prev ambos puntos a struct sí, entonces la lista está vacía. La siguiente macro se puede utilizar para inicializar la estructura:

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

esta manera:

struct lista my_list = LISTA_INIT_EMPTY(&my_list); 

Pero, ¿hay alguna manera de hacer lo mismo mediante la siguiente manera, sin parámetro de macro ?:

struct lista my_list = LISTA_INIT_EMPTY; 

he intentado lo siguiente, pero causó un error de compilación:

#define LISTA_INIT_EMPTY  { .next = &.next, .prev = &.next } 

Respuesta

6

Bueno, la única manera que veo es desagradable:

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

No es agradable en absoluto, ya que solo funciona si su variable se llama my_list. Y no hay una buena manera ya que this no existe en C.

¿Por qué no usar NULL en lugar de señalar a "esto"? Si esto no es satisfactorio, mantener la macro parametrizada es probablemente la mejor.

EDIT: (gracias a la observación de R a continuación, finalmente entendieron la necesidad):

Como no hay "esto" y que sólo se introduzca el nombre de la variable una vez, se sugiere emplear una macro como:

#define CREATE_EMPTY_LISTA(name) struct lista name = { .next=&name, .prev=&name } 

Y más adelante en el código:

CREATE_EMPTY_LISTA(my_list); // creates and initializez my_list at the same time 
+2

Creo PO quiere todas las listas, incluyendo el vacío inicial, para ser circular. Esto no es completamente irrazonable; a menudo elimina todos los casos de esquinas feas en las funciones de manejo de listas. –

+1

'CREATE_EMPTY_LISTA' es básicamente lo mismo que' LISTA_INIT_EMPTY' mencionado por el OP. –

+1

Sí, pero con una diferencia importante: 'struct lista my_list = LISTA_INIT_EMPTY (& my_list);' te obliga a repetir el nombre de la variable, lo que no es agradable y es bastante propenso a errores. 'CREATE_EMPTY_LISTA (my_list);' le permite no repetirlo. – Shlublu

0

No es verdad! Si define vacío como NULL en lugar de "sí", entonces usted puede hacerlo por:

#define LISTA_INIT_EMPTY {NULL,NULL}

0

al parecer esto no es posible, puesto que el bloque necesita saber la instancia.

también .next = &.next no funcionará ya que los tipos no coinciden. (struct lista* a struct lista**)

0

No, su inicializador crea una struct lista y luego asigna my_list a ella. Su idea de this no tiene sentido en este contexto, no apuntaría a my_list hasta después de haber sido asignada.

2

Tenga en cuenta que su técnica de lista de inicialización es similar lo que se utiliza en el código fuente del núcleo Linux para sus listas enlazadas (include/linux/list.h).

Para la inicialización de una lista cuando se declara la cabeza de lista, en lugar de tratar de hacer algo como:

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

Linux utiliza una macro que realiza tanto la delcaration y la inicialización (por lo que el usuario todavía tiene que usa el nombre solo una vez). Para su struct lista puede ser que parezca:

#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); 

Tome un vistazo a include/linux/list.h para todos los detalles. También hay buenas explicaciones de cómo funcionan las operaciones de listas (no toda ella es intuitiva):

Cuestiones relacionadas