Forward declara un tipo – ¿Cuál es la razón detrás de esto?

/* Forward declare a type "point" to be a struct. */ typedef struct point point; /* Declare the struct with integer members x, y */ struct point { int x; int y; }; 

¿Puedes explicar la razón detrás de la statement?

Me doy cuenta de que nadie ha respondido realmente a la pregunta que hizo, que fue

¿Cuál es la razón para declarar un tipo hacia adelante?

La respuesta es: C fue diseñado para que pueda comstackrse leyendo cada archivo una vez que va de arriba a abajo . Considere un lenguaje como C #:

 class C { B b; } class B { C c; } 

Observe que si el comstackdor va de arriba a abajo, el comstackdor llega a un campo de tipo B antes de saber qué es B Y, de hecho, el comstackdor de C # no lee el archivo completo una vez que va de arriba a abajo. Hace muchos pases sobre cada archivo, acumulando información a medida que avanza.

Ahora suponga que desea escribir un comstackdor de C # que pueda analizar el progtwig anterior sin hacer varias pasadas. De alguna manera, tendría que decirle al comstackdor antes de que se encontrara con el campo b que había un tipo llamado B ¡Pero no podemos simplemente mover la class B a la anterior a la class C porque eso volvería a crear el mismo problema, esta vez con C !

En nuestra versión imaginaria de una pasada de C #, podría decir que puede solucionar el problema de esta manera:

 class B; // Tell the compiler that B will be defined later. class C { B b; } class B { C c; } 

Y ahí tienes. Cuando el comstackdor llega a B b , sabe que B es una clase que se definirá más adelante. B ha sido declarado adelante .

Como C # siempre ha usado un enfoque de múltiples pasadas, no necesita este truco. Pero los diseñadores de C querían un enfoque de un solo paso, por lo que requieren la redundancia de una statement hacia adelante.

Este enfoque de un solo paso fue diseñado para facilitar la comstackción en el pasado, cuando las máquinas tenían pocos K de memoria y funcionaban a unos pocos miles de ciclos por segundo; El enfoque de C # de las exploraciones múltiples que construyen estructuras de datos complejas cada vez es costoso en comparación, y sería difícil en una máquina con velocidad y memoria limitadas.

Ahora, por supuesto, tenemos máquinas con billones de bytes de memoria (recuerde, la memoria es espacio en el disco ; ¡la RAM es solo un caché en el disco!) Que ejecutan miles de millones de ciclos por segundo, y aún así nos quedamos con el uso de técnicas para hacer La vida del escritor comstackdor más fácil en la década de 1970. Así es como se usa cuando se usa C.

 typedef struct point point; struct point { int x; int y; point *next; /* Could be used */ }; 

vs

 // typedef struct point point; struct point { int x; int y; point *next; /* error: unknown type name 'point' */ }; 

¿Qué es typedef?

El propósito de typedef es formar tipos complejos a partir de tipos de máquinas más básicos y asignar nombres más simples a tales combinaciones. Se utilizan con mayor frecuencia cuando una statement estándar es engorrosa, potencialmente confusa o puede variar de una implementación a otra.

Así que typedef struct point point; No es una statement directa que usted asume. Nombra a struct point como un point , de modo que cada vez que escriba un point , se referirá a struct point .

Así que ahora, puede declarar una variable como point p; en lugar de struct point p; .

Esta no es una statement de avance de un point , es un typedef para él * . El typedef te permite escribir.

 point p; 

en lugar de

 struct point p; 

El efecto de statement hacia adelante no se utiliza en su código. Sin embargo, con el typedef en su lugar, puede comenzar a usar el point como un nombre de tipo, en lugar de una etiqueta de struct , dentro de la statement de la estructura del point .

Una forma más común de lograr el mismo efecto es combinar la definición y el typedef , de esta manera:

 typedef struct point { int x; int y; } point; 

* El typedef pasa a declarar hacia adelante el tipo, pero eso es un “efecto secundario”.