2009-10-16 10 views
40

Mi chiedo dove sono memorizzate le variabili costanti. Nella stessa area di memoria delle variabili globali? O in pila?Dove sono le variabili costanti memorizzate in C?

+2

Mi chiedo quale grammatica sia ... – DevSolar

+1

Questa domanda non ha senso. Per favore riformulare – nall

+3

I * ha provato * a riformulare la domanda. Spero di aver capito bene l'OP. – DevSolar

risposta

37

Il modo in cui sono memorizzati è un dettaglio di implementazione (dipende dal compilatore).

Ad esempio, nel compilatore GCC, sulla maggior parte delle macchine, le variabili di sola lettura, le costanti e le tabelle di salto vengono posizionate nella sezione di testo.

+3

Questa è probabilmente l'unica risposta vera (anche se sarebbe più utile fornire metodi di implementazione popolari dopo averlo indicato.) –

+0

La semplice affermazione dei "dettagli di implementazione", sebbene corretta, potrebbe non essere la "migliore" risposta qui. Immagino che avremmo avuto a che fare con un principiante curioso, e come tale, la sfida qui è capire e rispondere: "Penso che volevi chiedere * questo * e, come tale, penso che tu voglia leggere * quello *". – Mizipzor

+1

@Lee: Se è definito come "implementazione", qualsiasi riferimento ai "metodi di implementazione più diffusi" indica che il codice potrebbe interrompersi nel prossimo aggiornamento del compilatore. Purtroppo, questo non è compreso da tutti, quindi molti di coloro che capiscono non "forniscono" informazioni su particolari implementazioni, nella speranza che i tipi di non comprensione ottengano il suggerimento ... – DevSolar

1

Di solito sono memorizzati nella sezione dati di sola lettura (mentre la sezione delle variabili globali ha permessi di scrittura). Quindi, provare a modificare la costante prendendo il suo indirizzo può causare una violazione di accesso, ovvero segfault.

Ma dipende davvero dall'hardware, dal sistema operativo e dal compilatore.

+2

"Quindi, provare a modificare la costante prendendo il suo indirizzo può causare una violazione di accesso, ovvero segfault." Oh, se solo fosse vero qui su OS X. L'ho appena testato, e funziona a malapena. –

+0

Su Windows, ad es. funziona solo per alcuni compilatori. per esempio. VC++ e gcc generano tale codice, ma Borland non lo fa (almeno non l'ultima volta che li ho usati, le cose potrebbero essere cambiate). –

+0

Quando provo a modificare la variabile const globale, ottengo l'errore di violazione di Access (poiché la variabile è memorizzata nel segmento di dati di sola lettura). Ma sono in grado di modificare la variabile const locale da quella memorizzata nello stack. – siva

1

Si tratta principalmente di un'ipotesi plausibile, ma direi che le costanti vengono solitamente memorizzate nelle istruzioni CPU effettive del programma compilato, come dati immediati. In altre parole, la maggior parte delle istruzioni include lo spazio per l'indirizzo per ottenere i dati, ma se è una costante, lo spazio può contenere il valore stesso.

3

Dipende dal compilatore, dalle funzionalità del sistema, dalla configurazione durante la compilazione.

gccputs costanti di sola lettura nella sezione .text, salvo istruzioni contrarie.

0

Globale e costante sono due parole chiave completamente separate. Puoi avere l'uno o l'altro, nessuno o entrambi.

Il punto in cui la variabile, quindi, viene memorizzata dipende dalla configurazione. Leggete un po 'il heap e lo stack, che vi daranno delle conoscenze per chiedere di più (e se posso, meglio e più specifiche) domande.

11

Si consideri il codice:

const int i = 0; 
static const int k = 99; 

int function(void) 
{ 
    const int j = 37; 
    totherfunc(&j); 
    totherfunc(&i); 
    //totherfunc(&k); 
    return(j+3); 
} 

In generale, i possono essere immagazzinate nel segmento di testo (si tratta di una sola lettura variabile con un valore fisso). Se non si trova nel segmento di testo, verrà memorizzato accanto alle variabili globali. Dato che è inizializzato a zero, potrebbe essere nella sezione 'bss' (dove le variabili azzerate sono solitamente allocate) o nella sezione 'data' (dove le variabili inizializzate sono solitamente allocate).

Se il compilatore è convinto che lo k non è utilizzato (il che potrebbe essere dato che è locale in un singolo file), potrebbe non apparire affatto nel codice oggetto. Se la chiamata a totherfunc() che fa riferimento a k non è stata commentata, è necessario assegnare un indirizzo a k da qualche parte, probabilmente nello stesso segmento di i.

La costante (se è una costante, è ancora una variabile?) j verrà probabilmente visualizzata nello stack di un'implementazione C convenzionale. (Se stavi chiedendo nel gruppo di notizie comp.std.c qualcuno direbbe che lo standard non dice che le variabili automatiche appaiono nello stack, fortunatamente SO non è comp.std.c!)

Si noti che ho forzato la visualizzazione delle variabili perché le ho passate per riferimento, presumibilmente a una funzione che prevede un puntatore a un numero intero costante. Se gli indirizzi non sono mai stati presi, allora j e k potrebbero essere completamente ottimizzati dal codice.Per rimuovere i, il compilatore dovrebbe conoscere tutto il codice sorgente per l'intero programma - è accessibile in altre unità di traduzione (file sorgente), e quindi non può essere rimosso facilmente. Non certo se il programma si conceda al caricamento dinamico delle librerie condivise - una di queste librerie potrebbe fare affidamento su quella variabile globale.

(Stilisticamente - le variabili i e j dovrebbero avere più a lungo, i nomi più significativi, questo è solo un esempio!)

+0

"(se è una costante, è ancora una variabile?)" Per definizione, no. –

+1

'j' può sicuramente essere visto come una variabile. La parola "variabile" non è definita in 'C', ma in C++' j' è una variabile. 'variable' è solo un oggetto con nome quindi, sia const o no. In C, i letterali e gli enumeratori sono chiamati 'constanti' - non penso che' j' sia chiamato una "costante" in C, anche perché non può apparire in espressioni costanti. –

0

Alcune costanti arfen't ancora memorizzati.

Considerare il seguente codice: int x = foo(); x *= 2;. È probabile che il compilatore trasformi la moltiplicazione in x = x+x; in quanto ciò riduce la necessità di caricare il numero 2 dalla memoria.

+0

...o a una moltiplicazione costante, dove il 2 verrebbe memorizzato nell'effettiva istruzione CPU –

+0

"Alcune costanti non sono nemmeno ..." dovrebbe essere "non lo sono" (l'avrei modificato ma per qualche motivo non posso cambia meno di 6 caratteri: /) – Rptk99

0

Potrebbe non essere memorizzato affatto.

Consideriamo alcuni codice come questo:

#import<math.h>//import PI 
double toRadian(int degree){ 
    return degree*PI*2/360.0; 
} 

Ciò consente al programmatore di raccogliere l'idea di ciò che sta accadendo, ma il compilatore può ottimizzare via un po 'di questo, e la maggior parte dei compilatori fanno, valutando espressioni costanti al momento della compilazione, il che significa che il valore PI potrebbe non essere affatto nel programma risultante.

25

seconda della segmentazione dei dati che un particolare processore segue, abbiamo cinque segmenti:

  1. Codice segmento - memorizza solo codice, ROM
  2. BSS (o Block Iniziato da simboli) di segmento - Negozi inizializzate globale e variabili statiche
  3. segmento
  4. Stack - memorizza tutte le varialbles locali e altre informazioni riguardanti l'indirizzo di ritorno della funzione ecc
  5. segmento Heap - tutte le allocazioni dinamiche accade qui
  6. segmento dati - negozi non inizializzate le variabili globali e statiche

nota che la differenza tra BSS e segmento di dati è che il primo negozio inizializzato varialbes globali e statiche e dei negozi più tardi quelle non inizializzate.

Ora, Perché sto parlando della segmentazione dei dati quando devo essere giusto dicendo dove sono le variabili costanti memorizzati ... c'è un motivo ad esso ...

Ogni segmento ha una regione di scrittura protetta dove tutti le costanti sono memorizzate.

Per esempio,

se ho un int const che è variabile locale, allora è memorizzato nella regione protetta da scrittura del segmento di stack. e se ho un globale che è inizializzato const var, allora è memorizzato in BSS e se ho una variabile const non inizializzata, allora è memorizzato nel segmento di dati ...

Per riassumere, "const" è solo un data QUALIFIER, il che significa che prima il compilatore deve decidere quale segmento deve essere memorizzato e quindi se la variabile è un const, allora si qualifica per essere memorizzato nella regione protetta da scrittura di quel particolare segmento.

Spero che questo chiarisca la maggior parte dei fraintendimenti ....:-)

Eventuali ulteriori commenti sono benvenuti ... :-)

+19

"e se ho un globale che è inizializzato const var, allora è memorizzato in BSS e se ho una variabile const non inizializzata, allora è memorizzato nel segmento di dati ..." .. Penso che dovrebbe essere come unitializzato -> bss, inizializzato -> segmento di dati – Subbu

+2

"se ho un const const che è una variabile locale, quindi viene memorizzato nella regione protetta da scrittura del segmento stack". Quale parte della pila è protetta da scrittura? – jimis

+3

Il segmento dati ha 2 parti: inizializzato e unitializzato. BSS -> segmento dati non inizializzato. – Mayank

1

offcourse no, perché

1) segmento bss memorizzate le variabili non inilized ovviamente un altro tipo è lì.

variabili
 (I) large static and global and non constants and non initilaized variables it stored .BSS section. 

     (II) second thing small static and global variables and non constants and non initilaized variables stored in .SBSS section this included in .BSS segment. 

2) segmento di dati è initlaized ha 3 tipi,

 (I) large static and global and initlaized and non constants variables its stord in .DATA section. 
     (II) small static and global and non constant and initilaized variables its stord in .SDATA1 sectiion. 
    (III) small static and global and constant and initilaized OR non initilaized variables its stord in .SDATA2 sectiion. 

i citato sopra mezzi di piccole e grandi depents su compilatore per esempio piccoli mezzi < di 8 byte e grandi mezzi> di 8 byte e valori uguali.

ma il mio dubbio è la costante locale dove si accarezza ??????

0

Proprio come un add on, come sapete che durante il processo di collegamento è stata decisa la disposizione della memoria dell'eseguibile finale. C'è un'altra sezione chiamata COMMON in cui sono posizionati i simboli comuni da diversi file di input. la sezione comune in realtà rientra nella sezione .bss.