2013-07-22 15 views
24

In C++ Conosco gli oggetti static e global prima della funzione main. Ma come sai, in C, non esiste questo tipo initialization procedure prima del main.Quando vengono inizializzate le variabili statiche e globali?

Per esempio, nel mio codice:

int global_int1 = 5; 
int global_int2; 
static int static_int1 = 4; 
static int static_int2; 
  • Quando sono queste quattro variabili inizializzate?
  • Dove i valori per l'inizializzazione come 5 e 4 vengono memorizzati durante la compilazione? Come gestirli durante l'inizializzazione?

EDIT:
Chiarimento della seconda domanda.

  • Nel mio codice che uso 5 a inizializzareglobal_int1, così come può il compilatore assegnare5 a global_int? Ad esempio, forse il compilatore prima memorizza il valore 5 da qualche parte (ad esempio una tabella) e ottiene questo valore quando inizia l'inizializzazione.
  • Per quanto riguarda "Come gestirli durante l'inizializzazione?", È davvero vago e io stesso non so come interpretare. A volte, non è facile spiegare una domanda. Trascuralo visto che non ho ancora completamente padroneggiato la domanda.
+0

Tutte e quattro le variabili hanno classe di memorizzazione statica. –

+0

@KerrekSB In che modo 'la classe di memoria statica' si riferisce alla mia domanda? – Zachary

+0

La classe di archiviazione determina il comportamento di inizializzazione. –

risposta

21

Per oggetti statici e globali, presumo che intendiate oggetti con durata di vita statica definita nello spazio dei nomi. Quando tali oggetti sono definiti con ambito locale, le regole sono leggermente diverse.

Formalmente, C++ inizializza tali variabili in tre fasi: 1. Zero inizializzazione 2. inizializzazione statico 3. dinamico inizializzazione Il linguaggio distingue anche tra variabili che richiedono inizializzazione dinamica, e quelle che richiedono statica inizializzazione: tutti gli oggetti statici (oggetti con statico durata) sono primo zero inizializzato, quindi oggetti con statico inizializzazione vengono inizializzati, quindi inizializzazione dinamica verifica.

Come semplice prima approssimazione, inizializzazione dinamica significa che qualche codice deve essere eseguito; in genere, l'inizializzazione statica non lo fa. Così:

extern int f(); 

int g1 = 42; // static initialization 
int g2 = f(); // dynamic initialization 

Un'altra approximization sarebbe che l'inizializzazione statica è supporti quello C (per le variabili con durata statica), dinamica tutto il resto.

Come il compilatore fa questo dipende, ovviamente, l'inizializzazione , ma su sistemi basati disco, dove l'eseguibile viene caricato nella memoria dal disco, i valori per statica inizializzazione sono parte dell'immagine su disco, e caricato direttamente dal sistema dal disco. Su un sistema classico Unix , variabili globali sarebbero divisi in tre "segmenti":

testo:
Il codice, caricato in una zona protetta da scrittura. Anche le variabili statiche con i tipi `const` verranno inserite qui.
dati:
Variabili statiche con inizializzatori statici.
BSS:
variabili statiche senza-inizializzatore (C e C++) o con dinamica inizializzazione (C++). L'eseguibile contiene alcuna immagine per questo segmento, e il sistema semplicemente imposta tutto a `0` prima di iniziare la vostra codice.

ho il sospetto che un sacco di sistemi moderni usano ancora qualcosa simile.

EDIT:

Un ulteriore osservazione: quanto sopra si riferisce a C++ 03. Per i programmi esistenti , C++ 11 probabilmente non cambia nulla, ma lo fa aggiungi constexpr (il che significa che alcune funzioni definite dall'utente possono ancora essere inizializzate statiche) e thread variabili locali, che apre una lattina completamente nuova di vermi.

+0

Thx James. La tua risposta è davvero meravigliosa. Nell'ultimo paragrafo hai menzionato l'inizializzazione dinamica che si trova nel segmento .bss. Perché? Intuitivamente, penso che dovrebbe essere nel segmento .data come è inizializzato. – Zachary

+0

Per disturbarti ancora. Come sai, dalla tua risposta, ho una comprensione migliore. Ma non conosco il principio dietro. Come sono state derivate queste regole linguistiche. Potresti dare qualche riferimento per me? Ecco un link [Specificare la classe di archiviazione] (http://en.cppreference.com/w/cpp/language/storage_duration). Dopo aver letto questa pagina, ero più confuso. Dovrebbero essere considerati due molti piccoli articoli. – Zachary

+0

@Zack L'inizializzazione dinamica non viene eseguita fino all'avvio del programma. Per quanto riguarda il caricamento dell'eseguibile, è zero inizializzato, e questo è tutto. –

1

Parafrasato dallo standard:

Tutte le variabili che non hanno durata di conservazione dinamica, non hanno filettatura durata memoria locale, e non sono locali, hanno durata di conservazione statica. In altre parole, tutti i globali hanno una durata di archiviazione statica.

Gli oggetti statici con inizializzazione dinamica non vengono necessariamente creati prima della prima istruzione nella funzione principale. È definita l'implementazione se questi oggetti vengono creati prima della prima istruzione in main, o prima del primo utilizzo di qualsiasi funzione o variabile definita nella stessa unità di traduzione della variabile statica da inizializzare.

Quindi, nel proprio codice, global_int1 e static_int1 sono definitivamente inizializzati prima della prima istruzione principale perché sono inizializzati staticamente. Tuttavia, global_int2 e static_int2 sono inizializzati dinamicamente, quindi la loro inizializzazione viene definita in base alla regola che ho menzionato sopra.

Per quanto riguarda il secondo punto, non sono sicuro di capire cosa intendi. Potresti chiarire?

3

Quando vengono inizializzate queste quattro variabili?

Come dici tu, questo accade prima dell'avvio del programma, cioè prima che main inizi. C non lo specifica ulteriormente; in C++, questi si verificano durante la fase di inizializzazione statica prima di oggetti con costruttori o inizializzatori più complicati.

Dove vengono memorizzati i valori per l'inizializzazione 5 e 4 durante la compilazione?

In genere, i valori diversi da zero sono memorizzati in un segmento di dati nel file di programma, mentre i valori zero sono in un segmento bss che appena si riserva di memoria sufficiente per le variabili. All'avvio del programma, il segmento di dati viene caricato in memoria e il segmento bss viene impostato su zero. (Naturalmente, lo standard di lingua non lo specifica, quindi un compilatore potrebbe fare qualcos'altro, come generare codice per inizializzare ogni variabile prima di eseguire main).

+0

Molti. Soprattutto per la seconda domanda. Una variabile è in realtà un'unità di memoria indirizzata. Quindi 5 è appena memorizzato nell'unità di memoria assegnata ad esso nella sezione/segmento di dati. – Zachary

+0

L'ho spiegato nel mio post per la seconda domanda. Mike, pensi che l'inizializzazione sia fatta durante il collegamento? Poiché dopo il processo di collegamento, i segmenti del programma sono fondamentalmente fissati! – Zachary

12

Premessa: La parola "statica" ha un gran numero di differenti significati in C++. Non confondersi.

Tutti gli oggetti hanno durata di memorizzazione statica. Questo perché non sono né automatici né dinamici. (Né thread-local, anche se thread-local è un po 'come statico.)

In C++, gli oggetti statici vengono inizializzati in due fasi: inizializzazione statica e inizializzazione dinamica.

  • inizializzazione dinamica richiede codice che deve essere eseguito, quindi questo accade per gli oggetti che iniziano con una chiamata costruttore, o dove l'inizializzatore è un'espressione che può essere valutato solo in fase di esecuzione.

  • inizializzazione statico è quando l'inizializzatore è noto staticamente e nessun costruttore deve eseguire. (L'inizializzazione statica è inizializzazione zero o inizializzazione costante.) Questo è il caso per le vostre variabili int con inizializzatore costante e si è certi che quelle sono effettivamente inizializzate nella fase statica.

  • (variabili Static-deposito con inizializzazione dinamica sono anche zero initialzed staticamente prima di tutto accada.)

Il punto cruciale è che la fase di inizializzazione statico doens't "run" a tutti. I dati sono lì fin dall'inizio. Ciò significa che non esiste alcun "ordine" o qualsiasi altra proprietà dinamica che riguarda l'inizializzazione statica. I valori iniziali sono hard-coded nel tuo programma binario, se vuoi.

Problemi correlati