No he escrito C durante mucho tiempo, por lo que no estoy seguro de cómo debo hacer este tipo de cosas recursivas ... Me gustaría que cada celda contenga otra celda, pero aparece un error líneas de "campo 'hijo' tiene tipo incompleto". ¿Qué pasa?
typedef struct Cell {
int isParent;
Cell child;
} Cell;
Respuestas:
Claramente, una celda no puede contener otra celda ya que se convierte en una recursión interminable.
Sin embargo, una celda PUEDE contener un puntero a otra celda.
fuente
Cell
todavía no está dentro del alcance.Cell*
acell->child
.struct
s en C básicamente almacena todos sus valores uno al lado del otro, sería imposible almacenar una estructura en sí misma (porque esa estructura tendría que contener otra y así sucesivamente, lo que llevaría a una estructura de memoria de tamaño infinito) .struct Cell
, vea esta respuesta .En C, no puede hacer referencia al typedef que está creando dentro de la estructura misma. Debe usar el nombre de la estructura, como en el siguiente programa de prueba:
Aunque probablemente sea mucho más complicado que esto en el estándar, puedes considerarlo como el compilador que conoce sobre
struct Cell
la primera línea de la líneatypedef
pero no sabetCell
hasta la última línea :-) Así es como recuerdo esa regla.fuente
Desde el punto de vista teórico, los idiomas solo pueden soportar estructuras autorreferenciales, no estructuras autoincluyentes.
fuente
Hay una forma de evitar esto:
Si lo declaras así, le dice al compilador que struct Cell y plain-ol'-cell son iguales. Entonces puedes usar Cell como de costumbre. Sin embargo, todavía tengo que usar struct Cell dentro de la declaración inicial.
fuente
struct Cell;
nuevo?struct Cell
.struct Cell;
redundante. Sin embargo, si por alguna razón coloca las dos últimas líneas en un archivo de encabezado que incluye antes de definir laCell
estructura con las primeras cuatro líneas, entonces el extrastruct Cell;
es necesario.typedef struct Cell Cell;
y haráCell
un alias parastruct Cell
. No importa si el compilador lo ha vistostruct Cell { .... }
antes.Sé que esta publicación es antigua, sin embargo, para obtener el efecto que estás buscando, puedes probar lo siguiente:
En cualquiera de los dos casos mencionados en el fragmento de código anterior, DEBE declarar la estructura de la celda secundaria como un puntero. Si no lo hace, obtendrá el error "campo 'hijo' tiene tipo incompleto". La razón es que "struct Cell" debe definirse para que el compilador sepa cuánto espacio asignar cuando se usa.
Si intentas utilizar "struct Cell" dentro de la definición de "struct Cell", entonces el compilador aún no puede saber cuánto espacio se supone que ocupa "struct Cell". Sin embargo, el compilador ya sabe cuánto espacio ocupa un puntero y (con la declaración directa) sabe que "Cell" es un tipo de "struct Cell" (aunque todavía no sabe qué tan grande es una "struct Cell") ) Entonces, el compilador puede definir una "Celda *" dentro de la estructura que se está definiendo.
fuente
Veamos la definición básica de typedef. typedef se usa para definir un alias para un tipo de datos existente, ya sea definido por el usuario o incorporado.
por ejemplo
La confusión aquí es con la estructura autorreferencial, debido a un miembro del mismo tipo de datos que no se definió anteriormente. Entonces, de manera estándar, puede escribir su código como: -
Pero la última opción aumenta algunas líneas y palabras adicionales con lo que generalmente no queremos hacer (somos tan vagos, ya sabes;)). Así que prefiera la Vista 2.
fuente
typedef
sintaxis es incorrecta (considere, por ejemplotypedef int (*foo)(void);
). Sus ejemplos de Vista 1 y Vista 2 no funcionan: hacenstruct Cell
un tipo incompleto, por lo que no puede usarlochild
en su código.Otro método conveniente es predefinir la estructura con la etiqueta de estructura como:
fuente
Una estructura que contiene una referencia a sí misma. Una ocurrencia común de esto en una estructura que describe un nodo para una lista de enlaces. Cada nodo necesita una referencia al siguiente nodo de la cadena.
fuente
Todas las respuestas anteriores son geniales, solo pensé en dar una idea de por qué una estructura no puede contener una instancia de su propio tipo (no una referencia).
Es muy importante tener en cuenta que las estructuras son tipos de 'valor', es decir, contienen el valor real, por lo que cuando declara una estructura, el compilador tiene que decidir cuánta memoria asignar a una instancia de la misma, por lo que pasa por todos sus miembros y agrega hasta su memoria para descubrir la memoria total de la estructura, pero si el compilador encontró una instancia de la misma estructura en el interior, entonces es una paradoja (es decir, para saber cuánta memoria necesita la estructura A, tiene que decidir cuánta memoria estructura A toma!).
Pero los tipos de referencia son diferentes, si una estructura 'A' contiene una 'referencia' a una instancia de su propio tipo, aunque todavía no sabemos cuánta memoria se le asigna, sabemos cuánta memoria se le asigna a una memoria dirección (es decir, la referencia).
HTH
fuente