In C, const
dovrebbe essere letta come sola lettura. Non definisce un tempo di compilazione.
const int a = 5;
Qui a
, è non un'espressione costante come richiesto dal C standard:
6.7.9 Inizializzazione
4 Tutte le espressioni in un inizializzatore per un oggetto che ha statico o filo la durata di archiviazione deve essere costante espressioni o stringhe letterali.
Quindi l'errore indica che si sta utilizzando un compilatore C89/C90. È possibile leggere l'input dell'utente per a
e dichiarare un variable length array, che è una funzione C99, che ha durata di archiviazione automatica.
Utilizzare #define
è un altro modo. Ma è semplicemente una sostituzione testuale e definisce un array con durata di archiviazione automatica. È lo stesso che definisce tu stesso lo int arr[5];
.
se si desidera allocare memoria su storage dinamico (comunemente noto come "heap"), è necessario utilizzare le funzioni famiglia malloc()
, che avranno una durata durante l'esecuzione del programma finché non si chiama free()
su di esso.
(Si noti che questo comportamento di const
è solo in C. C++ differisce in questo e funzionerà come previsto).
Se compilo il codice C89, non riesce con:
#include <stdio.h>
int main(){
const int a = 5;
int i;
int arr [a];
for (i = 0; i < 5; i++) {
arr[i] = i * 2;
}
printf("%d", arr[1]);
return 0;
}
$ gcc -Wall -Wextra -std=c89 -pedantic-errors test.c
test.c: In function âmainâ:
test.c:7:4: error: ISO C90 forbids variable length array âarrâ [-Wvla]
int arr [a];
^
perché C89 non supporta i VLA (Anche se gcc supporta come an extension anche in C89/C90). Quindi, se stai utilizzando un compilatore che non supporta C99, non puoi utilizzare VLA. Ad esempio, Visual Studio non supporta completamente tutte le funzioni C99 e C11. Sebbene, , VLA non sono uno di loro.
Ma lo stesso codice compila in C99 e C11 senza alcun problema:
$ gcc -Wall -Wextra -std=c99 -pedantic-errors t.c
$ gcc -Wall -Wextra -std=c11 -pedantic-errors t.c
è perché sono stati aggiunti gli array di lunghezza variabile (VLA) in C99. Si noti che i VLA sono stati resi facoltativi nello standard C11. Quindi un'implementazione potrebbe non supportare VLA in C11. È necessario eseguire un test con __STDC_NO_VLA__
per verificare se i VLA non sono supportati dall'implementazione.
Da 6.10.8.3 Conditional feature macros
__STDC_NO_VLA__
Il numero intero costante 1, inteso per indicare che l'implementazione non supporta le matrici di lunghezza variabile o variabilmente tipi modificati.
Personalmente non utilizzo VLA in quanto l'errore di allocazione non può essere trovato in modo da poter essere trovato se la dimensione dell'array è ragionevolmente grande. Per esempio.
size_t size = 8*1024;
int arr[size];
Nel frammento di cui sopra, se arr
allocazione fallita, non si sa fino a runtime. Che cos'è una dimensione "abbastanza piccola" per cui l'allocazione della memoria dipende dalla piattaforma. Quindi su una macchina, l'allocazione 1MB può avere successo e un'altra potrebbe fallire e la parte peggiore è che non c'è modo di cogliere questo fallimento.
Quindi l'uso di VLA è limitato e può essere utilizzato solo con piccoli array che si sa che avranno sempre successo su una determinata piattaforma. Ma in questo vorrei semplicemente codificare a macchina le dimensioni dell'array e occuparmi delle condizioni al contorno.
La tua postulazione secondo cui le alternative disponibili sono in gran parte "# define" o "malloc" è corretta: scegli una di queste due opzioni per risolverla. La risposta di l3x fa un buon lavoro di spiegazione del perché. – GrandOpener