Quando la memoria è allocata a variabili locali in C

Poiché le variabili locali sono anche chiamate variabili automatiche e si suppone che vengano allocate memoria in fase di esecuzione, quando si accede alla funzione.

int main(){ int a; // declaration return 0; } int main(){ int a[]; // compilation error, array_size missing return 0; } int main(){ int a[2]; // declaration, but can't work without array_size, // so at compile time it is checked! return 0; } 

La mia domanda è se sia solo una regola a dare array_size nella dichiarazione in C, o la memoria viene allocata in fase di compilazione per array (variabile locale ancora)

Come funziona?

Un array è una variabile secondo la programmazione C di K & R. pg n. 161.

Quando si dichiara una variabile locale, la sua dimensione è nota al momento della compilazione, ma l’allocazione della memoria avviene durante il tempo di esecuzione.

Quindi nei vostri esempi, l’array senza una dimensione è chiaramente un problema per il compilatore, in quanto non sa quale sia la dimensione da includere nel codice assemblatore.

Se non si conosce la dimensione di un array, è sempre ansible utilizzare i tipi di puntatore e malloc / free o anche alloca . I primi due operano su heap e alloca utilizza effettivamente stack.

L’eccezione degna di nota sono le variabili statiche. La memoria per loro è già allocata in fase di compilazione / collegamento e non può essere modificata in fase di runtime.

Esempi:

 int main(int argc, const char *argv[]) { int a; // a is a sizeof(int) allocated on stack } int main(int argc, const char *argv[]) { int a[2]; // a is a sizeof(int)*2 allocated on stack } int main(int argc, const char *argv[]) { int *a; // a is a sizeof(int*) allocated on stack (pointer) a = alloca(sizeof(int)*4); // a points to an area with size of 4 integers // data is allocated on stack } int main(int argc, const char *argv[]) { static int a; // a is allocated in data segment, keeps the value } 
 int main(){ int a[2]; return 0; } 

Qui, int a[2]; è una definizione di una variabile denominata a . a è una matrice di due int .

Quello che succede in pratica è che il compilatore emette il codice per utilizzare lo spazio nello stack per 2 oggetti int adiacenti (probabilmente 8 byte, ma la dimensione di int è fino all’implementazione). Ciò presuppone naturalmente che l’ottimizzatore non rimuova l’object perché non lo usi mai.

L’errore del compilatore che hai ottenuto per int a[999999999]; è dovuto a qualche limite rigido imposto dal compilatore, perché sa (o comunque presume) che non ci sarà mai abbastanza stack per quello.

Come sgar91 ha dichiarato nei commenti, un array come nel tuo esempio viene assegnato quando viene chiamata una funzione e deve essere determinata in dimensione. Se sono necessari array dinamici, è necessario allocare la memoria nell’heap.

 int *values = malloc(sizeof(int) * array_count); 

L’allocazione automatica avviene quando si dichiara una variabile automatica, come un argomento di funzione o una variabile locale . Lo spazio per una variabile automatica viene assegnato quando viene immessa l’istruzione composta contenente la dichiarazione e viene liberata quando si esce dall’istruzione composta.

Questo è il punto in C, dove array e puntatori non sono la stessa cosa.

Prendi questo esempio:

 int main(){ int a[5]; int * b = malloc(sizeof(int) * 5); printf("sizeof a = %d\n",sizeof a); printf("sizeof int[5] = %d\n",sizeof(int[5])); printf("sizeof b = %d\n",sizeof b); free(b); return 0; } 

Questo ritornerà:

 sizeof a = 20 sizeof int[5] = 20 sizeof b = 4 

La variabile a è dichiarata internamente come int [5], un puntatore intero che punta a un blocco di memoria con spazio per 5 numeri interi.

Per le variabili locali, la memoria che consumano è in pila. Ciò significa che devono avere una dimensione fissa nota al momento della compilazione, in modo che quando viene chiamata la funzione, la quantità esatta di memoria necessaria venga aggiunta allo stack modificando il valore del puntatore dello stack. Questo è il motivo per cui l’array deve avere una dimensione: il numero di byte sullo stack deve cambiare di una quantità fissa quando viene chiamata la funzione.

Le chiamate a malloc () e simili allocano memoria dall’heap; la memoria allocata in questo modo al runtime può essere di dimensioni variabili.

C’è una differenza tra le variabili locali e automatiche in C. Una variabile locale può essere automatica o statica , che determina se la memoria viene allocata nello stack o in modo permanente quando il programma viene eseguito per la prima volta.

Con questo codice:

 int main(){ int a[]; //compilation error, array_size missing return 0; } 

Questo è un array incompleto . L’errore è dovuto al fatto che il compilatore non sa quanti int è il programma da allocare.

Le dimensioni delle matrici dovrebbero essere note al momento della compilazione e si può passare direttamente alla dimensione della matrice o indirettamente, poiché la memoria viene decisa al momento della compilazione ma allocata in fase di esecuzione, ad eccezione dell’array di dimensioni variabili.