2009-07-22 17 views

risposta

89

Si dovrebbe dichiarare la variabile in un file di intestazione:

extern int x; 

e quindi definire in uno file C:

int x; 

In C, la differenza tra una definizione e una dichiarazione è che la definizione riserva spazio per la variabile, mentre la dichiarazione introduce semplicemente la variabile nella tabella dei simboli per collegare il tempo).

+3

** Entrambi ** sono dichiarazioni! Nell'ambito del file, il secondo non è una definizione (completa), ma una definizione _tentativa_. – Olaf

29

È possibile (dovrebbe) dichiararlo come extern in un file di intestazione e definirlo esattamente nel file 1 .c.

Si noti che il file .c dovrebbe anche usare l'intestazione e che il modello standard si presenta come:

// file.h 
extern int x; // declaration 

// file.c 
#include "file.h" 
int x = 1; // definition and re-declaration 
+0

Infatti * dovrebbe * usare sempre l'intestazione, in modo che se i tipi escono da whack tra la dichiarazione e la definizione il compilatore te lo dirà. – caf

+0

cat, hai ragione, lo ridiscuterò un po '. –

9

Se si dichiara come

int x; 

in un file di intestazione che viene poi inclusa in più luoghi, ci si ritroverà con più istanze di x (e potenzialmente compilare o problemi di collegamento).

Il modo corretto per avvicinarsi a questo è quello di avere il file di intestazione dire

extern int x; /* declared in foo.c */ 

e poi in foo.c si può dire

int x; /* exported in foo.h */ 

quindi è possibile includere il file di intestazione in ben luoghi come ti piace

3

La chiave è di mantenere invariate le dichiarazioni della variabile nel file di intestazione e nel file di origine.

Io uso questo trucco

------sample.c------ 
#define sample_c 
#include sample.h 

(rest of sample .c) 

------sample.h------ 
#ifdef sample_c 
#define EXTERN 
#else 
#define EXTERN extern 
#endif 

EXTERN int x; 

Sample.c viene compilata una sola volta e che definisce le variabili. Qualsiasi file che include sample.h viene assegnato solo "extern" della variabile; assegna lo spazio per quella variabile.

Quando si modifica il tipo di x, cambierà per tutti. Non dovrai ricordarti di cambiarlo nel file sorgente e nel file di intestazione.

+2

Come gestite l'inizializzazione? - extern int x = 6; darebbe un avvertimento alla maggior parte dei compilatori. – Dipstick

+0

@chrisharris: questa è una limitazione. Di solito ho un Init() in ogni modulo per inizializzare le variabili. – Robert

+0

Non ti sembra meno ingombrante avere la dichiarazione extern nell'intestazione e la definizione nel file C? Come @caf ha commentato, se i tipi non corrispondono si ottiene un avviso (io comunque includo sempre il file di intestazione nel file c corrispondente, dal momento che ho bisogno che tutte le funzioni abbiano un prototipo). – Gauthier

0

E questa soluzione?

#ifndef VERSION_H 
#define VERSION_H 

static const char SVER[] = "14.2.1"; 
static const char AVER[] = "1.1.0.0"; 

#else 

extern static const char SVER[]; 
extern static const char AVER[]; 

#endif /*VERSION_H */ 

L'unico limite che vedo è che la guardia includere non ti salva se si include due volte nello stesso file.

+1

1) La protezione #ifndef impedisce più definizioni in un file sorgente * single * (quindi le definizioni esterne non fanno nulla). 2) Dichiarare una variabile statica in un'intestazione significa che ogni file sorgente che lo include avrà la sua versione di quella variabile piuttosto che una singola variabile condivisa. Tecnicamente questo collegherà, ma il comportamento potrebbe non essere desiderato (potrebbe non notare come hai usato le variabili const in questo esempio, ma usalo per qualcosa di non-const e vedrai che conta). La risposta accettata è quasi sempre la soluzione appropriata. – Assimilater

Problemi correlati