Array di lunghezza variabile (VLA) in C e C ++

Possibile duplicato:
Array a variazione variabile nell’ambito del file

Ho alcuni concetti sul VLA e il suo comportamento che devo chiarire.

AFIK dal C99 è ansible dichiarare VLA in ambiti locali:

int main(int argc, char **argv) { // function 'main' scope int size = 100; int array[size]; return 0; } 

Ma è vietato negli ambiti globali:

 const int global_size = 100; int global_array[global_size]; // forbidden in C99, allowed in C++ int main(int argc, char **argv) { int local_size = 100; int local_array[local_size]; return 0; } 

Il codice sopra dichiara VLA in C99 perché il modificatore const non crea un valore in fase di compilazione. In C ++ global_size è un valore in fase di compilazione, quindi, la global_array non diventa un VLA.

Quello che devo sapere è: il mio ragionamento è corretto? Il comportamento che ho descritto è corretto?

Voglio anche sapere: perché il VLA in ambito globale non è permesso? sono proibiti sia in C che in C ++? Qual è la ragione per cui il comportamento degli array in ambito globale e locale era diverso?

Sì, il tuo ragionamento è corretto, è così che queste diverse forms di dichiarazioni e definizioni di array vengono visualizzate da C e C ++.

Come già affermato da altri, VLA con una vera lunghezza variabile (non const ) nell’ambito globale è difficile da comprendere. Quale sarebbe l’ordine di valutazione, ad esempio se l’espressione di lunghezza si riferirebbe a un object di una diversa unità di compilazione? C ++ non ha VLA, ma ha l’inizializzazione dynamic degli oggetti nell’ambito del file. E già questo ti dà un bel mal di testa, se devi fare affidamento sull’ordine di valutazione.

Questo lascia il piccolo spazio per C riguardo le espressioni di lunghezza che contengono un object qualificato const , che non è permesso. Ciò deriva dal fatto che tali oggetti non sono considerati “espressioni costanti intere” dallo standard C. Questo potrebbe cambiare nelle versioni future, ma fino ad ora il comitato C non ha ritenuto necessario consentire una cosa del genere: esistono costanti di enum che svolgono tale ruolo in C. La loro unica limitazione è che sono limitate a int in C, sarebbe bello avere anche loro size_t .

C ++ non supporta VLA, punto. La ragione per cui il secondo frammento di codice funziona in C ++ è che la parola chiave const crea una costante in fase di compilazione in C ++; in C, non è così.

C99 non supporta VLA al di fuori dell’ambito del blocco, periodo, indipendentemente da come si dichiara la variabile di dimensione. Notare che C2011 rende opzionale il supporto VLA.

Penso che la ragione fondamentale sia una variabile globale che ha un link, la sua dimensione deve essere nota al momento della compilazione. In caso contrario, come si potrebbe colbind il programma?

le variabili locali non hanno alcun collegamento e gli VLA sono allocati nello stack, che cresce dynamicmente durante l’esecuzione del programma.

C’è una differenza tra l’essere vietato e il non essere permesso. 😉

La funzionalità VLA è progettata per consentire l’uso dello spazio di stack per un array locale, per evitare l’uso di malloc per l’allocazione dell’heap. È principalmente un’ottimizzazione della velocità.

Ora si desidera utilizzare VLA al di fuori delle funzioni. Perché? Non c’è molto da guadagnare in senso orario evitando una singola chiamata malloc durante l’avvio del programma. E quale spazio di pila dovremmo usare per le variabili con una durata statica?

Quindi, per VLA globali, uno dei problemi (ci sono molte varianti sul tema) può essere mostrato qui:

 int size; int a; int v[size]; int b; 

…. in un altro file:

 extern int a; extern int b; 

Il linker dovrà sapere dove sono e sono in relazione l’uno con l’altro al momento del collegamento, o non sarà in grado di risolverli correttamente al momento del caricamento.