2015-09-08 15 views
14

Il seguente codice viene compilato correttamente senza alcun avviso su gcc.La struttura non dichiarata non causa avvisi

Si noti che non esiste una dichiarazione di inoltro per la struttura. Questo codice C e/o C++ è valido?

struct Foobar* f; 
struct Foobar* fun() { return 0; } 

int main() { f = 0; fun(); return 0; } 
+2

Sì, è valido. – erip

+7

La struttura è * dichiarata *, ma non * definita *. Questi due termini sono spesso usati in modo intercambiabile, ma significano cose diverse. –

+3

Questo è ciò che rende possibile che le strutture contengano puntatori al proprio tipo come membri (come le liste concatenate) - un tipo non ha bisogno di essere completamente dichiarato perché un puntatore a quel tipo sia valido. – DevSolar

risposta

26

Questo ha chiamato una struttura opaca e non è un errore. Dal momento che tutti i puntatori di struct sono ugualmente grandi in C, non è necessario sapere quali campi ha la struttura finché si limitano a manipolarli.

Provare a definire una struttura variabile Foobar (nessun puntatore) e si otterrà un errore di tipo incompleto.

Ciò consente di avere tipi con campi privati, ad es. il tipo FILE da stdio.h.

+4

Non necessariamente. * Definisci * una variabile di tipo 'struct Foobar' e otterrai un errore. Dichiarare semplicemente una variabile senza definirla ('extern struct Foobar hello;') non darà alcun errore. – hvd

+1

@hvd è un punto delicato ma ok, ho risolto la mia risposta. – jforberg

11

valido in C.

struct Foobar* f; 

è uguale a:

struct Foobar; 
struct Foobar* f; 

In C si dichiara un tipo incompleto struct Foobar e dichiara un oggetto puntatore a un tipo incompleto.

Il tipo può essere completato in un'altra unità di traduzione. (In C ci sono 3 tipi di tipo: oggetto, funzione e incompleto).

Non è possibile creare oggetti di tipo incompleta o ottenere la dimensione del tipo:

struct Foobar x; // not valid 
sizeof (struct Foobar); // not valid 

ma è possibile creare puntatori a tipi incompleti (struct Foobar* g;) o typedef (typedef struct Foobar Foobar;).

+0

Sarebbe legale avere "extern struct Foobar x;" e prendere il suo indirizzo? – supercat

+0

@supercat: I * imagine * si otterrebbe un errore linker a meno che non ci sia realmente una 'struct Foobar x' che giace da qualche parte. – Kevin

+0

@ Kevin: Naturalmente, * qualcuno * dovrebbe avere una dichiarazione per questo, ma la domanda è se "extern" dovrebbe essere elencato come un altro scenario ammissibile dal punto di vista del codice che usa la struttura senza scopo se non per prendere il suo indirizzo. – supercat

Problemi correlati