2011-02-24 17 views
13

consideri il codice:Ambito di una variabile esterna principale C

#include <stdio.h> 

int x; 

int main (void) 
{ } 

Il valore di x è 0 all'interno main. Ma perché è così? Non ho dichiarato che sia static. O è assunto static in quanto è al di fuori di una funzione?

Se quanto sopra è vero, in che modo lo rende diverso da uno extern?

+0

Puoi chiarire la tua domanda su 'extern'? –

+0

Se voglio dichiarare una variabile esterna, non è fatta allo stesso modo? – Kanishk

+0

La differenza tra questo e un esterno è che un esterno è esterno e questo non lo è. –

risposta

19

Non è né staticextern. È una variabile visibile per l'unità di compilazione in cui si trova e, inoltre, sarà visibile da tutte le unità di compilazione che dichiarano x una variabile extern.

Perché sto dicendo che non è né staticextern?

Se era extern, allora, ci deve essere un'unità di compilazione diverso con x dichiarazione su di esso. Chiaramente questa è la tua unica unità di compilazione.

Se fosse static, quindi, non è consentito il riferimento extern alla variabile x definita in questa unità di compilazione. Sappiamo che potremmo facilmente dichiarare una variabile extern a questo x dichiarato qui.

Perché 0 è assegnato a x? Perché, in C, tutte le variabili globali vengono inizializzate su 0. Lo dice in 6.7.8 (10) dello standard C99.

+0

Aah, vedo. Quindi, perché viene inizializzato su 0? – Kanishk

+0

@Kanishk: considera una funzione che racchiude il * file * su cui lavori. Questo è lo scopo di questa dichiarazione. L'ambito di 'extern' si estende su più file. – Eelvex

+0

@Kanishk: aggiornato la mia risposta un po '. @Eelvex: grazie per aver chiarito che ... –

1

compilatore inizializzato il valore di x per essere 0.

E 'una variabile globale che è visibile dall'interno main()

+0

Ma quando voglio che sia una variabile esterna, faccio lo stesso. Quindi qual è la differenza? – Kanishk

+0

Non seguo la tua domanda? Cosa ti aspetti che non stai vedendo? –

+0

La risposta di Pablo si prende cura di quella parte. – Kanishk

2

Non è statico. È globale. Puoi dichiararlo extern in una diversa unità di compilazione, ma lo spazio verrà assegnato per questo in questa. Globali sono sempre inizializzati a 0 se non vengono forniti gli inizializzatori, a proposito.

+0

Quindi quando lo chiamo un'altra unità di compilazione che usa la parola chiave 'extern', la rende una variabile esterna, ma per questo file è globale. Destra? – Kanishk

+0

@Kanishk: È globale in entrambi i file, è solo che la dichiarazione 'extern' per esso nell'altro file non causa allocazione di spazio. Ottiene l'indirizzo dal linker, che ottiene l'indirizzo da questo file. – nmichaels

+0

Aah! Grazie. Lo capisco adesso. – Kanishk

5

Quando diciamo che le variabili di "durata di archiviazione statica" sono inizializzate a 0 in modo implicito, non intendiamo che sia necessario mettere la parola chiave "statica" davanti a esse.

"durata di archiviazione statica" è semplicemente un tipo specifico di durata di archiviazione per gli oggetti che indicano che la loro memorizzazione dura per l'intera durata del programma. Questo tipo di durata di archiviazione viene utilizzato per le variabili dichiarate nell'ambito del file (come la variabile) e le variabili statiche locali.

+2

Ah, i molti significati di "statico". –

+2

parole chiave sensibili al contesto ...... –

3

6.2.2/5: "Se la dichiarazione di un identificatore per un oggetto ha uno scope di fi le e non speci fi ca di classe di memoria, il suo collegamento è esterno."

Questo è collegamento, tuttavia, non scope. La tua dichiarazione di x avrebbe l'ambito del file in entrambi i casi. static e extern non influenzano l'ambito. È inizializzato a 0 perché x ha una durata di archiviazione statica (vedere 6.2.4/3 e/5).

In generale, è necessario tenere presente 6.2.2./ 4:

Per un er identi fi dichiarato con il classe di archiviazione specifico er extern in un ambito in cui una previa dichiarazione di che identi fi catore è visibile, se il collegamento interno o esterno il prima dichiarazione fi speci ca, la il collegamento dell'identificatore alla dichiarazione successiva è lo stesso del collegamento specificato a la dichiarazione precedente.

Quindi dichiarare con extern non equivale a dichiarare senza identificatore di classe di memoria. Nel tuo esempio non c'è nessuna dichiarazione preliminare, però.

+0

Lo standard è il Santo Graal, in un'altra domanda che ho chiesto prima, le persone citavano lo standard. Grazie però :-) – Kanishk

+0

@ Kanishk: citare lo standard è un processo in corso, più ti riferisci ad esso, più il suo stile e il gergo iniziano a dare un senso. Quindi puoi evitare di basarti su esempi di tutorial, regole mezzo ricordate e istinto istinto :-) –

1

x è una variabile globale, dispone di uno spazio allocato quando il programma viene avviato e viene inizializzato su 0 (in genere, tuttavia, è necessario un inizializzatore esplicito).

La parola chiave "statica" ha due significati diversi.

1)

static int x; 

int main() { } 

Questo limita il campo di applicazione x al singolo file. Sebbene sia ancora una variabile globale, il linker non sarà in grado di collegare riferimenti a x da altri file.

2)

int main() { 
    static int x; 
} 

Questo trasforma efficacemente x in una variabile globale. Sebbene l'ambito sia ancora all'interno della funzione principale, lo spazio viene allocato a livello globale e il suo valore verrà mantenuto tra le chiamate a main().

0

Sembra una domanda da fare a casa, ma morderò comunque.

Per utilizzare la x è stato definito qui in una classe o una funzione da un altro file, è necessario utilizzare

extern int x; 

sopra l'uso della variabile x (come nell'intestazione), allora si può usare x solo come faresti in main(). extern dice al compilatore che stai usando una variabile che è definita/istanziata altrove.

Se si desidera che esista prima dell'esecuzione del main, si utilizza static che viene gestito prima di main() in esecuzione. In altre parole carica lo spazio di memoria con le variabili prima di avviare qualsiasi elaborazione (nel main).

Per quanto riguarda il motivo per cui è 0 all'avvio, è probabile che solo il compilatore fornisca un valore di base. Non tutti i compilatori lo fanno, a meno che non mi sbagli, molti ti daranno solo ciò che era nello spazio di memoria assegnato a x che potrebbe essere qualsiasi cosa. In altre parole ti danno la memoria completa con qualsiasi dato (o dati parziali) era in esso in anticipo.

+2

Com'è questo compito? Non ti sto chiedendo di scrivere il codice per me. Sto chiedendo qualcosa che ho provato. Le domande sui compiti a casa non sono così. – Kanishk