C Kompilierungsfehler: "Objekt mit variabler Größe darf nicht initialisiert werden"

97

Warum erhalte ich die Fehlermeldung "Objekt mit variabler Größe darf nicht initialisiert werden" mit dem folgenden Code?

int boardAux[length][length] = {{0}};
Hallo Welt
quelle
Wie in der ausgezeichneten Antwort von David Rodriguez hervorgehoben: Wenn die Länge eine Variable ist, benötigen Sie ein Memset, aber wenn die Länge eine Konstante für die Kompilierungszeit ist, wird die Anweisung einwandfrei kompiliert.
Casey
ffwd bis 2020 -enum {length = 0xF } ; int boardAux[length][length] = {0};
Chef Gladiator

Antworten:

121

Ich gehe davon aus, dass Sie einen C99-Compiler verwenden (mit Unterstützung für Arrays mit dynamischer Größe). Das Problem in Ihrem Code ist, dass der Compiler zu dem Zeitpunkt, an dem er Ihre Variablendeklaration sieht, nicht wissen kann, wie viele Elemente sich im Array befinden (ich gehe auch hier davon aus, dass der Compilerfehler lengthkeine Kompilierungszeitkonstante ist).

Sie müssen dieses Array manuell initialisieren:

int boardAux[length][length];
memset( boardAux, 0, length*length*sizeof(int) );
David Rodríguez - Dribeas
quelle
Ich kann für diesen Zweck auch malloc verwenden, was ist mit der zweiten Frage, die ich nach Pavel's Antwort geschrieben habe
helloWorld
@helloWorld: Mit Stapel zugewiesenen Arrays, printf( "%d", boardAux[1][2] )kompiliert gut. Der Compiler kennt die Größen und weiß, an welcher Position im Speicher sich das (1,2) -te Element befindet. Wenn Sie die dynamische Zuordnung verwenden, ist das Array eindimensional und Sie müssen die Mathematik selbst durchführen:printf("%d", boardAux[ 1*length + 2 ])
David Rodríguez - Dribeas
@AndreyT: Danke, dass Sie auf den Fehler im memsetAufruf hingewiesen haben. Ich habe es gerade korrigiert.
David Rodríguez - Dribeas
Warum erhalte ich diesen Fehler in C99 - Compiler , wenn ich das Set lengthzu sein static? In C ++ 14 funktioniert es gut.
Muhamed Cicak
25

Sie erhalten diesen Fehler, weil Sie in der Sprache C keine Initialisierer mit Arrays variabler Länge verwenden dürfen. Die Fehlermeldung, die Sie erhalten, sagt im Grunde alles.

6.7.8 Initialisierung

...

3 Der Typ der zu initialisierenden Entität muss ein Array unbekannter Größe oder ein Objekttyp sein, der kein Array-Typ variabler Länge ist.

Ameise
quelle
Wo hast du das gefunden? Kannst du mir einen Link geben?
Hallo Welt
1
@helloWorld: Dies ist aus dem Sprachstandard (C99). Eine "funktionierende" Kopie mit TC3-Updates erhalten Sie hier open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
AnT
5
Es gibt Themen, für die einige Ihnen immer nicht glauben, wenn Sie nur die informelle Erklärung geben. Arrays mit variabler Länge sind eines dieser Themen. +1 für die Angabe des Standards.
Pascal Cuoq
14

Dies gibt Fehler:

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

Dies gibt auch Fehler:

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

Aber das funktioniert gut:

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

Sie müssen den Wert folgendermaßen setzen:

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

Nach dem Deklarieren des Arrays

int boardAux[length][length];

Die einfachste Möglichkeit, die Anfangswerte als Null zuzuweisen, ist die Verwendung der for-Schleife, auch wenn sie etwas langwierig sein kann

int i, j;
for (i = 0; i<length; i++)
{
    for (j = 0; j<length; j++)
        boardAux[i][j] = 0;
}
Krishna Shrestha
quelle
2
memsetist einfacher und schneller.
Cacahuete Frito
1

Die Frage ist bereits beantwortet, aber ich wollte auf eine andere Lösung hinweisen, die schnell ist und funktioniert, wenn die Länge zur Laufzeit nicht geändert werden soll. Verwenden Sie das Makro #define vor main (), um die Länge zu definieren, und in main () funktioniert Ihre Initialisierung:

#define length 10

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

Makros werden ausgeführt, bevor die eigentliche Kompilierung und Länge eine Kompilierungszeitkonstante sind (wie von David Rodríguez in seiner Antwort angegeben). Vor dem Kompilieren wird die Länge durch 10 ersetzt.

Sergey
quelle
0

Deklarieren Sie einfach die Länge als Nachteil. Wenn dies nicht der Fall ist, sollten Sie den Speicher dynamisch zuweisen

Azizou
quelle
2
Ich denke, Sie müssen nachschlagen, was const bedeutet!
Holger
@ Holger: Bist du sicher? Wenn die Variable, die die Länge enthält (nicht das Array selbst, sondern die Arraylänge), eine Konstante ist, kennt der Compiler die Länge, die zum Initialisieren des Arrays verwendet werden soll. Zum Beispiel "int length = 5; int array [length];" gibt den Fehler aber " const int length = 5; int array [length];" kompiliert ganz gut.
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;
}
Codetheft
quelle
1
Willkommen bei Stack Overflow! Bitte lesen Sie die Anleitung zum Schreiben einer guten Antwort: stackoverflow.com/help/how-to-answer Ihre aktuelle Antwort scheint vage zu sein und hat keine Erklärung dafür
gybandi
-5

Für C ++ separate Deklaration und Initialisierung wie folgt.

int a[n][m] ;
a[n][m]= {0};
Munawir
quelle
1
Keine C ++
Cacahuete Frito
Oben wird nur A [n] [m] initialisiert, nicht das gesamte Array. int a [n] [m]; memset (a, 0, (n m sizeof (int)); // mem des Arrays löschen Die meisten Compiler erlauben dies: int a [n] [m] = {0}; // initialisiere alle Mitglieder auf 0
Chris Reid
-9

Du kannst das nicht machen. Der C-Compiler kann so etwas auf dem Stapel nicht ausführen.

Sie müssen Heap und dynamische Zuordnung verwenden.

Was Sie wirklich tun müssen:

  • Berechnen Sie die Größe (n m sizeof (Element)) des benötigten Speichers
  • Rufen Sie malloc (Größe) auf, um den Speicher zuzuweisen
  • Erstellen Sie einen Accessor: int * access (ptr, x, y, rowSize) {return ptr + y * rowSize + x; }}

Verwenden Sie * access (boardAux, x, y, size) = 42, um mit der Matrix zu interagieren.

Pavel Radzivilovsky
quelle
Noch eine Frage: Warum erhalte ich einen Fehler bei ungültiger Verwendung des Arrays mit nicht angegebenen Grenzen? printf ("% d", Tafel [i] [j]);
Hallo Welt
10
-1 C99 ermöglicht die dynamische Zuordnung im Stapel als Benutzercode (ohne Initialisierung). Es ist nicht erforderlich, dynamische Zuordnungen durchzuführen.
David Rodríguez - Dribeas
@helloWorld, da Array-Dimensionen bekannt sein müssen.
Pavel Radzivilovsky