2015-05-23 23 views
7

Sappiamo tutti come dichiarare una struttura in C:Dichiarazione di una struttura: typedef struct name name;

struct Label1{ /* variables */ } Label2; // As I learned 

Ma io voglio sapere perché questo codice funziona senza dichiarare 'nome struct':

typedef struct name s_name; 

o è in realtà, lo fa a digitare il codice

struct name; 

significa che ho dichiarato 'struct name' come una struttura vuota o qualcosa del genere?

Esempio di codice:

typedef struct Data Data; 
struct Data{ /*variables*/ }; 

Se nella prima linea dati struct è dichiarata come un vuoto uno, poi nella seconda è come sto redeclaring con i membri.

Qual è la spiegazione di questo punto?

+2

strutture C sono nominalmente digitati, cioè identità tipo all'interno di un'unità di traduzione è determinato dal nome; 'struct name' è sufficiente per dichiarare un nuovo tipo, ma il tipo sarà incompleto finché non verrà trovata un'altra dichiarazione completa (definizione aka); puoi avere dei puntatori agli oggetti con tipo incompleto, ma ovviamente non potrai accedere ai membri o usarli per dichiarare le variabili; una dichiarazione di tipo incompleta è anche nota come dichiarazione anticipata; uno dei suoi usi sono i puntatori opachi – Christoph

+1

@ Michael Heidelberg "Sappiamo tutti come dichiarare una struttura in C" - dopo la tua domanda non sono sicuro che sia vero. :) –

risposta

8

Qualcosa di simile:

struct MyStruct; 

è chiamato un riferimento in avanti. Crea un tipo incompleto e dice al compilatore che ci sarà un tipo di quel nome (ed è una struttura - funziona allo stesso modo per i sindacati), ei dettagli "seguono dopo". Di questo tipo non è possibile definire variabili, fino a quando non si completa il tipo.

typedef struct MyStruct MyType; 

Definirà semplicemente il nome del tipo come struttura. Questo è ancora un tipo incompleto.

Tuttavia, si può prendere un puntatore ad un tipo incompleto:

MyType *my_t_pointer; 
struct MyStruct *my_s_pointer; 

Questo è utile per una struttura di avere puntatori a oggetti dello stesso tipo quando si fornisce la dichiarazione completa, "completare" il tipo :

struct MyStruct { 
    struct MyStruct *next; 
}; 

in realtà questo è l'unico modo per creare nodi per liste, alberi, e tutti gli altri-strutture dati ricorsive. Questa è una parte importante dei programmi C (a volte nascosti).

Inoltre, questo meccanismo viene utilizzato per nascondere i dettagli di implementazione. Le funzioni nell'intestazione devono solo conoscere la struttura esistente per prendere/passare i puntatori ad essa. L'uso di queste funzioni non deve conoscere i dettagli della struttura (ma in questo modo non può allocarlo, quindi il modulo deve coprire tutti gli aspetti che necessitano di conoscere i dettagli sulla struttura). La dichiarazione completa è solo all'interno del file di implementazione del modulo. Questi puntatori sono chiamati "opachi" in quanto non è possibile "guardare attraverso", cioè accedere ai campi della struttura in quanto semplicemente non sono noti ad esso.

my_module.h:

struct MyStruct; 

extern void my_init(struct MyStruct *obj); 

my_module.c:

struct MyStruct { 
    int f1; 
    ... 
}; 

my_init(struct MyStruct *obj) 
{ 
    ... 
} 
+0

L'ho capito; grazie per questa spiegazione –

2

Il typedef dichiara S_Name come un alias per il nome struct in modo da poter dichiarare le variabili, ad esempio:

s_name *sptr; 

La linea

struct name; 

dichiara che c'è un tipo struct denominato nome senza definire il suo contenuto. Questo di solito è fatto per poter dichiarare variabili come puntatori al tipo di struct. Non è possibile dichiarare le variabili del tipo di struttura effettivo finché non è stato definito.

+1

Capisco che qui ci siano due notazioni: dichiarare un struttura ; e definendo il suo contenuto? –

+0

Ususlly quelli sono combinati ma è possibile dichiarare un tipo di struct senza definirne il contenuto. Questa è una dichiarazione incompleta, vedi anche il commento di Christoph. –