2009-12-08 24 views
7

Alcune volte è necessario pre-dichiarare una variabile statica e quindi usarla. Ma il nome della variabile di questa dichiarazione potrebbe essere sbagliato, e il compilatore non può rilevarlo, oops!Come dichiarare una variabile statica ma non definirla

Esempio:

/* lots of codes */ 
static some_type some_name; /* pre-declaration */ 
          /* but it may define "some_name" */ 
/* use some_name */ 

/* lots of codes */ 

static some_type someName = initialization; /* definition */ 
/* use someName */ 

/* lots of codes */ 

"some_name" e "SomeName" sono diverse, si usa una variabile sbagliato al inizio. Se la dichiarazione di pre-dichiarazione non definisce alcuna cosa, il compilatore rileverà l'errore.

Quindi, come dichiarare una variabile statica ma non definirla? Come posso modificare la pre-dichiarazione in una nuova che rende il compilatore in grado di rilevare nomi errati?

+4

statico significa che è stato caricato in fase di compilazione. Perché non vuoi inizializzarlo? – Woot4Moo

+1

Woot4Moo: Fare una variabile globale 'statica' in C significa che non è visibile al di fuori dell'attuale "unità di compilazione", di solito un file .c e tutti i suoi header. Tutte le variabili globali che non sono "esternamente" sono allocate nello spazio in fase di compilazione. – Anton

risposta

9

gcc darà un avvertimento nel caso che hai descritto:

./x.c:3010: warning: 'someName' defined but not used 

Soluzione: fare quello che stai facendo attualmente, ma non ignorare gli avvisi del compilatore;)

Edit:

Con la tua domanda aggiornata: No, non credo che ci sia un modo per dichiarare semplicemente una variabile statica (senza anche definirla).

La soluzione comune è solo per assicurarsi che tutte le variabili di ambito globale siano dichiarate una sola volta, con un inizializzatore se ne hanno bisogno.

+0

"someName" è anche in uso, ho cambiato il mio post un po ', grazie. –

8
static some_type some_name; /*definition */ 

La variabile statica nome_non è stata inizializzata da 0; è la definizione, non solo una dichiarazione.

IMO, una variabile statica non può essere dichiarata solo in C utilizzando un identificatore esterno poiché il suo collegamento è sempre interno.

+1

Non penso che tu stia usando "IMO" correttamente.Non sembra un'opinione. –

+1

È opinione di Prasoon; si allinea anche con lo standard, quindi la sua opinione è corretta (secondo lo standard). –

0

È necessario pre-dichiarare la variabile? In caso contrario, inserire l'inizializzatore nell'unica dichiarazione. Se il tuo inizializzatore non è una costante (che richiederebbe C++, non C, IIRC), allora capisco perché è necessario pre-dichiararlo prima di alcune funzioni che lo usano. Ma poi tutto ciò che serve per l'inizializzatore potrebbe essere pre-dichiarato prima di esso.

Quindi metti i tuoi difetti costanti e le variabili statiche nella parte superiore di ogni file, così il tuo inizializzatore per la statica può arrivare subito dopo le costanti. Quindi non è necessaria una riga di inizializzazione separata.

In ogni altro caso, caf ha ragione: può valere la pena ottenere il codice da compilare con gcc solo per ottenere il beneficio dei suoi avvisi. L'ho fatto per g ++ per una GUI MFC in C++. (compilare, non eseguire!)

AFAIK C non ha un modo per scrivere una definizione debole che produrrà un errore se non c'è una definizione con un inizializzatore in seguito. C'è sempre uno 0 implicito, poiché la variabile va nella sezione BSS.

-1

Se capisco il tuo problema, forse non lo affronti nel modo giusto.

Non sarebbe meglio con extern SomeType someVar_; che dice al programma, so che questa variabile sarà nota, ma non voglio dirti cosa è ora.

È possibile, pertanto, in un file separato dichiarare la variabile dicono

static SomeType SomeVar_;

Nel file, mettere

extern SomeType SomeVar_

E che mettere l'inizializzazione dove vuoi.

+1

Ciò causerà un errore del linker, poiché la definizione 'static' ha un collegamento interno e non può essere raggiunta dal file in cui è stata dichiarata usando' extern'. –

2

Un piccolo sfondo:

Come altri hanno sottolineato, variabili statiche sono hanno collegamento interno, il che significa che essi possono essere utilizzati solo nella stessa "unità di compilazione" o sorgente. Ciò significa che non è possibile dichiararlo in un file di intestazione, assegnare un valore ad esso in una unità di compilazione e aspettarsi che quel valore appaia in un altro.

Quando si inizializza una variabile globale (statica o meno), il compilatore inserisce semplicemente il valore iniziale nel file eseguibile nella posizione di memoria allocata per la variabile. In altre parole, ha sempre un valore iniziale. Ovviamente è sempre possibile sovrascrivere il valore utilizzando una dichiarazione di assegnazione.

Suggerimenti:

Se davvero non si conosce il valore della variabile a tempo di compilazione, allora si dovrebbe assegnare dinamicamente nella funzione di inizializzazione.

static some_type some_variable; /* = 0 by default */ 

/* some code */ 

void MyInitializations() 
{ 
    some_variable = some_value; 
} 

Se si vuole dichiarare la variabile in un unico luogo, diciamo un file di intestazione, e definirlo in un file di origine, quindi si dovrebbe utilizzare una dichiarazione di 'extern', che dice al compilatore di non preoccuparsi di dove il la variabile è. Il linker troverà la posizione della variabile molto simile a come trova una funzione in un altro file e inserisce l'indirizzo.

Intestazione:

extern some_type some_variable; 

File sorgente 1:

void UseSomeVariable() 
{ 
    x = some_variable; 
} 

file di Fonte 2:

some_type some_variable = some_value; 

/* possible also uses some_variable */ 

Se si desidera solo per dichiarare la variabile in un unico luogo e definirlo in un altro, non usare la parola chiave 'statica'. Lo svantaggio di questo è che non è possibile utilizzare la stessa variabile globale in diverse unità di compilazione (file .c) e non è possibile utilizzarlo in un file di intestazione.

3

Non è possibile creare una dichiarazione non definita (vale a dire "pre-dichiarare" nella terminologia) di un oggetto con collegamento interno in linguaggio C.

Il più vicino possibile è una definizione provvisoria, che è ciò che avete nel vostro esempio. Ma in caso di un errore di battitura, la definizione produrrà implicitamente una definizione indipendente, non un errore del linker.

Problemi correlati