Storia della domanda:
Nel linguaggio C, a volte è necessario che una struttura "conosca" un'altra, ma la definizione di entrambe le strutture dipende l'una dall'altra (annidamento reciproco). In questo caso, non è possibile definire completamente una struttura prima di dichiarare l'altra. A tal fine, in C è prevista la dichiarazione anticipata (forward declaration) delle strutture.
Problema:
Senza la dichiarazione anticipata, il compilatore non sa che tipo ha incontrato all'interno della struttura e restituirà un errore su un tipo sconosciuto. Spesso si verifica un errore quando cerchiamo di creare una struttura che contenga un'altra per valore, anziché per puntatore, o scriviamo la sintassi in modo errato.
Soluzione:
La dichiarazione anticipata viene applicata se è necessario creare un puntatore a una struttura senza rivelarne la definizione completa. La sintassi è struct A;. La definizione completa (struct A { ... };) può essere fornita successivamente.
Esempio di codice:
struct B; // dichiarazione anticipata struct A { int val; struct B *link; }; struct B { int id; struct A *parent; };
Caratteristiche chiave:
È possibile avere un campo di tipo "altra struttura per valore" attraverso la dichiarazione anticipata?
No, la dichiarazione anticipata consente di utilizzare il tipo solo sotto forma di puntatore, altrimenti si verificherà un errore: la dimensione del tipo è sconosciuta.
struct B; // ok struct A { struct B b; // errore: dimensione di B sconosciuta };
Dove è corretto posizionare la dichiarazione anticipata quando si lavora con file diversi?
La dichiarazione anticipata si colloca nell'intestazione se la struttura è utilizzata solo come puntatore. La definizione completa può trovarsi in un'altra intestazione o nel file di implementazione.
La dichiarazione anticipata influisce sulla dimensione delle strutture e sulla corretta allocazione di memoria?
No, perché C non conosce la dimensione della "struttura indefinita", e un puntatore ha sempre la stessa dimensione per quel compilatore, indipendentemente dal tipo dichiarato.
Nel file di intestazione, entrambi i moduli contenevano strutture con campi l'uno per l'altro per valore. La compilazione è fallita con un errore di tipo indefinito.
Vantaggi:
Svantaggi:
Uno dei programmatori ha utilizzato la dichiarazione anticipata e puntatori, minimizzando le dipendenze eccessive negli header. La compilazione e la manutenzione del codice sono diventate più semplici.
Vantaggi:
Svantaggi: