se questa struttura deve essere usata da qualche altro file func.c come si fa?
Quando un tipo viene utilizzato in un file (cioè file func.c), deve essere visibile. Il modo peggiore per farlo è copiarlo e incollarlo in ogni file sorgente necessario.
Il modo giusto è metterlo in un file di intestazione e includere questo file di intestazione ogni volta che è necessario.
dobbiamo aprire un nuovo file di intestazione e dichiarare la struttura lì e includere quell'intestazione nel func.c?
Questa è la soluzione che mi piace di più, perché rende il codice altamente modulare. Vorrei codificare la tua struttura come:
#ifndef SOME_HEADER_GUARD_WITH_UNIQUE_NAME
#define SOME_HEADER_GUARD_WITH_UNIQUE_NAME
struct a
{
int i;
struct b
{
int j;
}
};
#endif
Metterei le funzioni che utilizzano questa struttura nella stessa intestazione (la funzione che fa parte "semanticamente" della sua "interfaccia").
E di solito, potrei denominare il file dopo il nome della struttura e utilizzare di nuovo quel nome per scegliere le protezioni dell'intestazione definite.
Se devi dichiarare una funzione usando un puntatore alla struttura, non avrai bisogno della definizione completa della struttura. Una semplice dichiarazione anticipata come:
struct a ;
Sarà sufficiente e diminuisce l'accoppiamento.
oppure possiamo definire la struttura totale nel file di intestazione e includerla sia in source.c che in func.c?
Questo è un altro modo, un po 'più semplice, ma meno modulare: alcuni codici che richiedono solo la tua struttura per funzionare dovrebbero comunque includere tutti i tipi.
In C ++, questo potrebbe portare a complicazioni interessanti, ma questo è fuori tema (nessun tag C ++), quindi non approfondirò.
quindi come dichiarare quella struttura come esterna in entrambi i file. ?
Non riesco a vedere il punto, forse, ma Greg Hewgill ha un'ottima risposta nel suo post Come dichiarare una struttura in un'intestazione che deve essere utilizzata da più file in c? .
dobbiamo digitarlo allora come?
- Se stai usando C ++, non farlo.
- Se stai usando C, dovresti.
Il motivo è che la gestione della struttura in C può essere un problema: devi dichiarare la parola chiave struct ovunque venga utilizzata:
struct MyStruct ; /* Forward declaration */
struct MyStruct
{
/* etc. */
} ;
void doSomething(struct MyStruct * p) /* parameter */
{
struct MyStruct a ; /* variable */
/* etc */
}
Mentre un typedef ti consentirà di scriverlo senza la parola chiave struct.
struct MyStructTag ; /* Forward declaration */
typedef struct MyStructTag
{
/* etc. */
} MyStruct ;
void doSomething(MyStruct * p) /* parameter */
{
MyStruct a ; /* variable */
/* etc */
}
È importante mantenere ancora un nome per la struttura. scrittura:
typedef struct
{
/* etc. */
} MyStruct ;
creerà solo una struttura anonima con un nome digitato e non sarai in grado di dichiararlo in avanti. Quindi mantieni il seguente formato:
typedef struct MyStructTag
{
/* etc. */
} MyStruct ;
Quindi, sarai in grado di utilizzare MyStruct ovunque tu voglia evitare di aggiungere la parola chiave struct e continuare a utilizzare MyStructTag quando un typedef non funzionerà (cioè dichiarazione in avanti)
Modificare:
Corretto il presupposto errato sulla dichiarazione della struttura C99, come giustamente osservato da Jonathan Leffler .
Modifica 01/06/2018:
Craig Barnes ci ricorda nel suo commento che non è necessario mantenere nomi separati per il nome della struttura "tag" e il suo nome "typedef", come ho fatto sopra per motivi di chiarezza.
In effetti, il codice sopra potrebbe essere scritto come:
typedef struct MyStruct
{
/* etc. */
} MyStruct ;
IIRC, questo è in realtà ciò che fa C ++ con la sua dichiarazione struct più semplice, dietro le quinte, per mantenerlo compatibile con C:
// C++ explicit declaration by the user
struct MyStruct
{
/* etc. */
} ;
// C++ standard then implicitly adds the following line
typedef MyStruct MyStruct;
Tornando a C, ho visto entrambi gli usi (nomi separati e stessi nomi) e nessuno ha svantaggi che conosco, quindi usare lo stesso nome rende la lettura più semplice se non usi "spazi dei nomi" separati C per strutture e altri simboli .
struct b
, ma poi la tua strutturaa
dichiara un tipo non utilizzato (dovresti probabilmente definire un nome di membro, forsek
, dopo la parentesi graffa di chiusura interna e prima del punto e virgola.