PDA

View Full Version : [C] Le variabili globali sono tutte inizzializzate di default del compilatore C?!


Matrixbob
11-03-2007, 15:55
In che modo sono inizializzate?!
A 0?! Quindi direi che sono azzerate no?!

Se la risposta è si allora di conseguenza questa dichiarazione globale:

/* Variabili esterne per evitare il passaggio di troppi parametri tra funzioni */
int enclosure=NO, titolo=NO, descrizione=NO;
int count_item=0, canale_numero=0, side_pages=0;
char enclosure_url[SIZEBUF], enclosure_localpath[SIZEBUF];
char enclosure_nomefile[SIZEBUF], enclosure_type[SIZEBUF];
char *descrizione_strptr[MAXLINES], *enclosure_str, *titolo_str, *canale_titolo;

ha il solo scopo di rendere il codice + leggibile ed intuitivo?! Giusto?!

xorshadow
11-03-2007, 16:30
In C nessuna area di memoria viene inizializzata automaticamente. Al momento della creazione di un buffer(o di una variabile) statico o dinamico, questo contiene valori non predicibili.
Per fare quello che tu vorresti, protresti incapsulare la variabile globale all'interno di una funzione dichiarando la stessa variabile come static e quindi iniziallizzarla e ritornarla.

cionci
11-03-2007, 16:49
/* Variabili esterne per evitare il passaggio di troppi parametri tra funzioni */
No, è assolutamente stilisticamente brutto.
Se devi passare troppe variabili è possibile che tu abbia progettato male la suddivisione in funzioni. Ad esempio potresti aver funzioni troppo lunghe.
Se ciò non è vero potresti raggrupparle in strutture e passare la sola struttura.

Le variabili globali solitamente sono inizializzate a 0, ma non sono sicuro che sia obbligatorio, anzi, credo che sia una di quelle cose che lo standard lascia all'implementazione del compilatore.

Matrixbob
11-03-2007, 17:17
OOOK, il prossimo programma gli starò attento.
Ormai è quello che è e da qui devo andare avanti.
CMQ anche sul Kernigan lo dice.

Quello della inizializzazione invece non ne sono sicuro, ma l'avevo letto da qualche parte.

cionci
11-03-2007, 17:46
Molti compilatori lo fanno, ma non è detto che lo facciano tutti ;)

cionci
11-03-2007, 17:51
CMQ anche sul Kernigan lo dice.
Il K&R ha anche 40 anni ;)

Matrixbob
11-03-2007, 17:54
Cionci farò esperienza e migliorerò, anche grazie al vostro aiuto.

xorshadow
11-03-2007, 17:54
Molti compilatori lo fanno, ma non è detto che lo facciano tutti

Oltre a non farlo tutti, quelli che lo fanno ti stanno solo facendo un favore!
Se poi cerchi di compilare con qualche opzione di ottimizzazione della velocità puoi star certo che nessun compilatore ti inizializzarà niente.
E ci sono dei motivi dietro:
1) E' costoso
2) E' inutile, perchè il compilatore non può sapere a priori quale è il valore di default di una variabile perchè non sa quale semantica rappresenta.
Quindi dare per scontata l'inizializzazione della memoria è un errore di programmazione.

cionci
11-03-2007, 18:26
Al contrario, l'inizializzazione a zero è a costo zero, perché il valore dell'inizializzazione delle variabili globali e statiche viene automaticamente caricato dall'immagine dell'eseguibile.
Semplicemente durante la creazione della parte riguardante i dati all'interno dell'eseguibile, il valore delle variabili non inizializzate viene impostato a zero.

Comunque non sono sicuro che lo imponga lo standard, l'unica cosa è questa.

xorshadow
11-03-2007, 19:02
Al contrario, l'inizializzazione a zero è a costo zero, perché il valore dell'inizializzazione delle variabili globali e statiche viene automaticamente caricato dall'immagine dell'eseguibile.

Se carica un valore di inizializzazione vuol dire che la variabile viene inizializzata, e se non sbaglio non si sta parlando di questo, anzi si sta parlando del contrario, cioè se NON viene inizializzata.
Comunque, se la variabile non è esplicitamente inizializzata nel codice sorgente, quando viene caricato l'eseguibile, viene semplicemente riservato (ma non viene assolutamente ne letto ne scritto) dello spazio in memoria per tale variabile.


Semplicemente durante la creazione della parte riguardante i dati all'interno dell'eseguibile, il valore delle variabili non inizializzate viene impostato a zero.

E questo ha un costo ovviamente. Impostare qualcosa costa di più del NON impostare.

71104
11-03-2007, 19:31
non ho letto tutti i post ma dico la mia sperando di non essere ripetitivo: non devi assolutamente affidarti al fatto che le variabili (globali o non) in C vengano inizializzate automaticamente a zero o qualche altro valore perché afaik lo standard non prevede nessuna inizializzazione implicita.

aldilà di questo però posso dirti che, per cause dovute al funzionamento del compilatore e di Windows stesso, accade che quando compili un .exe per Windows le variabili globali non inizializzate sono quasi sempre inizializzate come aree di memoria completamente azzerate. ma vedila solo come una curiosità tecnica, anche perché vale solo per le variabili globali e non per quelle locali, che spesso invece assumono valori difficilmente predictable.

PS: di Linux non so nulla in merito :Prrr:

cionci
11-03-2007, 19:34
Chiariamo che si parla solo di variabili globali e statiche. Per questo nell'eseguibile c'è una sezione dedicata a queste variabili e tutte vengono inizializzate, anche quelle che non lo sono con valore pari a zero.
Questo proprio per una questione di prestazioni, immaginati questa situazione:

int x = 0;
int y;
int z = 0;

Come codifichi nell'eseguibile questa situazione ?
Ci possono essere due scelte:
- riservare 12 byte ed inizializzare x e z a runtime
- scrivere 12 byte nell'eseguibile che descrivono il valore di tutte le variabili (anche quelle non inizializzate, assegnandogli un valore scelto, zero in molti casi) e prendere tutto il blocco e metterlo in memoria

La prima necessita anche che ci sia del codice che inizializza le variabili a runtime. Quindi c'è, oltre allo spazio e al tempo necessario per caricare in memoria il codice che deve inizializzare le variabili, anche il tempo perso nell'esecuzione delle istruzioni. Fai conto che un semplice mov memoria, valore sono 1 byte di opcode, 4 byte per l'indirizzo della memoria e 4 byte per il valore e questo per ogni variabile da inizializzare.

La seconda è la più semplice e la più veloce perché consente di trasferire in burst direttamente TUTTA l'immagine dell'eseguibile in memoria (ovviamente se non c'è bisogno di un caricamento rilocante). Infatti visto che devo trasferire già il codice trasferire anche i dati ha un costo minimo.

Il riservare spazio si fa soltanto per le variabili locali...quelle sì che mantengono il valore che c'era prima nelle rispettive locazioni dello stack che sono state loro riservate.

71104
11-03-2007, 19:34
ah, e dimenticavo: per il C++ invece il discorso è molto diverso in quanto una variabile potrebbe essere di tipo class, ed in tal caso esiste un'inizializzazione implicita dovuta al costruttore. però credo che tu non possa fare affidamento all'inizializzazione dei campi di quella classe non esplicitamente inizializzati nel costruttore.

Matrixbob
11-03-2007, 19:53
A me a scuola han detto come a Cionci.
Anche 71XXX ha notato che di fatto in Winzoz succede.
Succede anche in Linux/Unix.

La faccenda del costono lasciamola perdere perchè la complessità spaziale e temporale va considerata asintoticamente.
Praticamente quelle poche istruzioni sono insignificanti.

CMQ io inizializzo anche le globali.
Poi ci penserà il compilatore a sistemare tutto. :)

[PS]
CMQ il C mi sta martoriando le balle. :D
Quando finirò il progetto spero di non toccarlo +.

xorshadow
11-03-2007, 19:56
Chiariamo che si parla solo di variabili globali e statiche. Per questo nell'eseguibile c'è una sezione dedicata a queste variabili e tutte vengono inizializzate, anche quelle che non lo sono con valore pari a zero.


Anche le variabili globali e statiche vengono create nello stack (non credo proprio che vengano create nello heap o nell'area del codice o peggio nell'area dati in cui ci sono dati "costanti" e non variabili).
Non confonderti con le variabili costanti.

Matrixbob
11-03-2007, 20:02
Non confonderti con le variabili costanti.

Le DEFINE?!
No no io mi ricordo che insegnavano le VAR globali.

xorshadow
11-03-2007, 20:07
A me a scuola han detto come a Cionci.

Cioè? Voglio sapere quale cosa in particolare.


Anche 71XXX ha notato che di fatto in Winzoz succede.
Succede anche in Linux/Unix.

Sul fatto che può succede siamo d'accordo tutti. Ma nessun programmatore serio si affiderebbe ad un "può succedere che il mio programma vada bene".


La faccenda del costono lasciamola perdere perchè la complessità spaziale e temporale va considerata asintoticamente.
Praticamente quelle poche istruzioni sono insignificanti.

Il costo era per spiagare il perchè non vengono inizializzate e comunque, anche l'inizializzazione può avere un peso se rapportato all'enorme numero di variabili di un programma.

xorshadow
11-03-2007, 20:09
Le DEFINE?!
No no io mi ricordo che insegnavano le VAR globali.

Chi ha parlato di DEFINE?
Parlo di cose del tipo

const int blabla;

71104
11-03-2007, 20:14
Anche 71XXX ha notato che di fatto in Winzoz succede. succede a causa di una particolarità (documentata!) nel meccanismo dell'allocazione delle pagine di memoria virtuale in Win32: le pagine allocate sono inizializzate a zero, cioè sono sempre completamente azzerate. le variabili globali (o locali statiche) non inizializzate di un eseguibile risiedono solitamente in particolari sezioni dell'eseguibile che hanno raw size = 0 e virtual size > 0 (ovvero: nel file non occupano spazio, ma nell'immagine in memoria dell'eseguibile si); questo fa si' che le pagine dedicate a quelle sezioni non subiscano nessuna inizializzazione se non quella da parte di Windows dovuta appunto alla loro allocazione.

ora vedo se ritrovo in MSDN la parte che documentava l'inizializzazione delle pagine di memoria virtuale...

EDIT - ecco qua: http://msdn2.microsoft.com/en-us/library/aa366887.aspx (leggere le primissime righe)
vero è che si potrebbe anche precisare che l'inizializzazione è documentata relativamente a quella funzione, e non al kernel; di conseguenza non si può fare affidamento sull'"inizializzazione implicita" in un ipotetico sistema che supporti Win32 per compatibilità; e aldilà di questo troppi sono i meccanismi che stanno dietro all'azzeramento implicito delle variabili non inizializzate, tutti meccanismi che potrebbero teoricamente (anche se poco probabilmente) cambiare e che riducono comunque la portabilità dei tuoi sorgenti, e sui quali quindi non puoi basarti. ribadisco: prendi tutto questo come una curiosità tecnica :)

ilsensine
12-03-2007, 09:19
le variabili globali (o locali statiche) non inizializzate di un eseguibile risiedono solitamente in particolari sezioni dell'eseguibile che hanno raw size = 0 e virtual size > 0 (ovvero: nel file non occupano spazio, ma nell'immagine in memoria dell'eseguibile si); questo fa si' che le pagine dedicate a quelle sezioni non subiscano nessuna inizializzazione se non quella da parte di Windows dovuta appunto alla loro allocazione.
Su linux è più o meno la stessa cosa, i dati non inizializzati finiscono in una regione elf chiamata BSS che serve appunto a questo.
Di norma questa regione è inizializzata a 0 (guai se non fosse inizializzata! Perché? ;) ), e gli ultimi gcc anzi spostano di default le inizializazzioni esplicite a 0 in BSS.