Errore di compilazione C: "L'oggetto di dimensioni variabili potrebbe non essere inizializzato"


97

Perché ricevo l'errore "Impossibile inizializzare l'oggetto di dimensioni variabili" con il codice seguente?

int boardAux[length][length] = {{0}};

Come sottolineato nell'eccellente risposta di David Rodriguez: se la lunghezza è una variabile, hai bisogno di memset, ma se la lunghezza è una costante del tempo di compilazione, l'istruzione viene compilata correttamente.
Casey

ffwd al 2020 -enum {length = 0xF } ; int boardAux[length][length] = {0};
Chef Gladiator

Risposte:


121

Presumo che tu stia utilizzando un compilatore C99 (con supporto per array di dimensioni dinamiche). Il problema nel tuo codice è che nel momento in cui i compilatori vedono la tua dichiarazione di variabile non possono sapere quanti elementi ci sono nell'array (presumo anche qui, dall'errore del compilatore che lengthnon è una costante del tempo di compilazione).

È necessario inizializzare manualmente quell'array:

int boardAux[length][length];
memset( boardAux, 0, length*length*sizeof(int) );

Posso usare anche malloc per questo scopo, che dire della seconda domanda, l'ho scritta dopo la risposta di Pavel
helloWorld

@ helloWorld: con array allocati nello stack, si printf( "%d", boardAux[1][2] )compila bene. Il compilatore conosce le dimensioni e sa in quale posizione in memoria si trova il (1,2) -esimo elemento. Se utilizzi l'allocazione dinamica, l'array è unidimensionale e devi eseguire i calcoli da solo:printf("%d", boardAux[ 1*length + 2 ])
David Rodríguez - dribeas

@AndreyT: Grazie per aver segnalato l'errore nella memsetchiamata. L'ho appena corretto.
David Rodríguez - dribeas

Perché ottengo questo errore nel compilatore C99 quando ho impostato lengthsu essere static? In C ++ 14 funziona bene.
Muhamed Cicak

25

Viene visualizzato questo errore perché in linguaggio C non è consentito utilizzare inizializzatori con array di lunghezza variabile. Il messaggio di errore che stai ricevendo dice praticamente tutto.

6.7.8 Inizializzazione

...

3 Il tipo di entità da inizializzare deve essere un array di dimensioni sconosciute o un tipo di oggetto che non è un tipo di array di lunghezza variabile.


dove l'hai trovato, puoi darmi un link?
helloWorld

1
@ helloWorld: viene dallo standard linguistico (C99). Puoi ottenere una copia "funzionante" con gli aggiornamenti TC3 qui open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
AnT

5
Ci sono argomenti per i quali alcuni non ti crederanno sempre se fornisci solo la spiegazione informale. Gli array a lunghezza variabile sono uno di questi argomenti. +1 per la citazione dello standard.
Pascal Cuoq,

15

Questo dà errore:

int len;
scanf("%d",&len);
char str[len]="";

Questo dà anche errore:

int len=5;
char str[len]="";

Ma funziona bene:

int len=5;
char str[len]; //so the problem lies with assignment not declaration

Devi dare valore nel modo seguente:

str[0]='a';
str[1]='b'; //like that; and not like str="ab";

2

Dopo aver dichiarato l'array

int boardAux[length][length];

il modo più semplice per assegnare i valori iniziali come zero è usare il ciclo for, anche se potrebbe essere un po 'lungo

int i, j;
for (i = 0; i<length; i++)
{
    for (j = 0; j<length; j++)
        boardAux[i][j] = 0;
}

2
memsetè più semplice e veloce.
Cacahuete Frito

1

La domanda ha già una risposta, ma volevo sottolineare un'altra soluzione che è veloce e funziona se la lunghezza non deve essere modificata in fase di esecuzione. Usa la macro #define prima di main () per definire la lunghezza e in main () la tua inizializzazione funzionerà:

#define length 10

int main()
{
    int boardAux[length][length] = {{0}};
}

Le macro vengono eseguite prima della compilazione effettiva e la lunghezza sarà una costante del tempo di compilazione (come indicato da David Rodríguez nella sua risposta). Sostituirà effettivamente la lunghezza con 10 prima della compilazione.


0

Dichiara semplicemente che la lunghezza è un contro, se non lo è dovresti allocare la memoria in modo dinamico


2
Penso che tu debba cercare cosa significa const!
Holger

@Holger: sei sicuro? Se la variabile che contiene la lunghezza (non l'array stesso, ma la lunghezza dell'array) è una costante, il compilatore conosce la lunghezza da utilizzare per inizializzare l'array. Ad esempio, "int length = 5; int array [length];" restituisce l'errore ma " const int length = 5; int array [length];" si compila bene.
Casey

0
int size=5;
int ar[size ]={O};

/* This  operation gives an error -  
variable sized array may not be 
initialised.  Then just try this. 
*/
int size=5,i;
int ar[size];
for(i=0;i<size;i++)
{
    ar[i]=0;
}

1
Benvenuto in Stack Overflow! Si prega di leggere la guida su come scrivere una buona risposta: stackoverflow.com/help/how-to-answer La tua risposta attuale sembra vaga e non ha alcuna spiegazione
gybandi

-5

Per la dichiarazione separata C ++ e l'inizializzazione come questa ..

int a[n][m] ;
a[n][m]= {0};

1
Non una domanda in C ++
Cacahuete Frito

Sopra inizializza solo A [n] [m], non l'intero array. int a [n] [m]; memset (a, 0, (n m sizeof (int)); // cancella mem dell'array La maggior parte dei compilatori lo consente: int a [n] [m] = {0}; // inizializza tutti i membri a 0
Chris Reid

-9

Non puoi farlo. Il compilatore C non può fare una cosa così complessa sullo stack.

Devi usare l'heap e l'allocazione dinamica.

Cosa devi veramente fare:

  • dimensione di calcolo (n m sizeof (element)) della memoria che ti serve
  • chiama malloc (size) per allocare la memoria
  • creare una funzione di accesso: int * access (ptr, x, y, rowSize) {return ptr + y * rowSize + x; }

Usa * access (boardAux, x, y, size) = 42 per interagire con la matrice.


un'altra domanda, perché ricevo un errore di utilizzo non valido dell'array con limiti non specificati? printf ("% d", board [i] [j]);
helloWorld

10
-1 C99 consente l'allocazione dinamica nello stack come codice utente (esclusa l'inizializzazione). Non è necessario eseguire allocazioni dinamiche.
David Rodríguez - dribeas

@ helloWorld perché le dimensioni dell'array devono essere note.
Pavel Radzivilovsky
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.