¿Cómo resuelve C la definición circular cuando un puntero en la estructura apunta a la estructura en sí?

Estoy acostumbrado a codificar como abajo por mucho tiempo.

Pero, ¿cómo resuelve el comstackdor de C el problema de definición circular? ¿O ese problema realmente existe?

struct node { int data; struct node *next; // circular definition for "struct node" type? }; 

AGREGAR 1

O, en una máquina de 32 bits, ¿puedo tratar un poco struct node * next miembro struct node * next como un miembro de tipo entero sin signo de 32 bits? Eso me hace sentir mejor.

AGREGAR 2

La razón por la que pienso en una definición circular es que cuando el comstackdor se encuentra con algo como next -> data o next -> next , tiene que saber el desplazamiento exacto de cada miembro para agregarlo al next puntero para obtener la ubicación correcta de cada miembro. Y ese tipo de cálculo requiere el conocimiento del tipo de cada miembro. Entonces para el miembro next , puede surgir el problema de la definición circular:

El tipo de next es struct node * , el tipo de struct node contiene a next , el tipo de next es struct node *

ADD 3

¿Y cómo calcula el comstackdor el sizeof(struct node) ?

ADD 4

Bueno, creo que el concepto crítico para entender este problema aparentemente circular es que el tamaño de un puntero no es relevante para el tipo al que apunta. Y el tamaño se fija en una máquina específica. El tipo de un puntero solo es significativo en tiempo de comstackción para que el comstackdor genere instrucciones para el cálculo del puntero.

next es un struct node * , que es solo un puntero, no un struct node , por lo que no hay una definición circular real. No se requieren los detalles de una estructura para averiguar cómo hacer un puntero a ella.

Para abordar sus apéndices:

  1. Aunque eso es más o menos preciso y probablemente funcionará, no está garantizado por el estándar, y usted no debería hacerlo.
  2. Nuevamente, struct node y struct node * son tipos completamente diferentes. Un struct node * no contiene ningún otro objeto.

Déjame contestar tus preguntas en orden:

Pero, ¿cómo resuelve el comstackdor de C el problema de definición circular?

struct node *next; no es una definición circular, struct node es un tipo incompleto, a next se define como un miembro con type struct node * , que es solo un puntero.

¿O ese problema realmente existe?

No, no es realmente un problema. De hecho, podría tener miembros definidos como punteros a cualquier estructura indefinida.

O, en una máquina de 32 bits, ¿puedo tratar un poco struct node *next miembro struct node *next como un miembro de tipo entero sin signo de 32 bits?

No debe hacer suposiciones sobre el tamaño real, el desplazamiento o la alineación de los miembros de la estructura. Una máquina de 32 bits puede tener tamaños de punteros que no son de 32 bits, no importa siempre que los utilice como punteros, no como números enteros.

La razón por la que pienso en una definición circular es que cuando el comstackdor se encuentra con algo como next->data o next->next , tiene que saber el desplazamiento exacto de cada miembro para agregarlo al next puntero para obtener la ubicación correcta de cada miembro.

Eso es correcto, pero cuando el comstackdor analiza dicho código, la definición de la estructura está completa y puede determinar el desplazamiento de los data y los next miembros.

¿Y cómo calcula el comstackdor el sizeof(struct node) ?

Después de analizar la definición de la estructura, el comstackdor tiene toda la información necesaria para calcular el tamaño de las instancias de la estructura. Para tal cálculo, se supone que todos los punteros a estructuras y / o uniones tienen el mismo tamaño.

Bueno, creo que el concepto crítico para entender este problema aparentemente circular es que el tamaño de un puntero no es relevante para el tipo al que apunta. Y el tamaño se fija en una máquina específica. El tipo de un puntero solo es significativo en tiempo de comstackción para que el comstackdor genere instrucciones para el cálculo del puntero.

Un tamaño de puntero es relevante para el tipo al que apunta, y en algunas architectures, diferentes tipos de punteros pueden tener diferentes tamaños. Sin embargo, el estándar C especifica algunas restricciones:

  • Todos los tipos de punteros se pueden convertir a void * y back.
  • Los punteros a todas las estructuras y uniones tienen el mismo tamaño.

En la mayoría de las architectures modernas, y específicamente en los sistemas compatibles con Posix, todos los tipos de punteros estándar tienen el mismo tamaño.