Erreur de compilation C: "L'objet de taille variable ne peut pas être initialisé"

98

Pourquoi est-ce que je reçois l'erreur «L'objet de taille variable ne peut pas être initialisé» avec le code suivant?

int boardAux[length][length] = {{0}};
Bonjour le monde
la source
Comme indiqué dans l'excellente réponse de David Rodriguez: si la longueur est une variable, vous avez besoin de memset, mais si la longueur est une constante de compilation, alors l'instruction se compile très bien.
Casey le
ffwd to 2020 -enum {length = 0xF } ; int boardAux[length][length] = {0};
Chef Gladiator

Réponses:

124

Je suppose que vous utilisez un compilateur C99 (avec prise en charge des tableaux de taille dynamique). Le problème dans votre code est qu'au moment où les compilateurs voient votre déclaration de variable, ils ne peuvent pas savoir combien d'éléments il y a dans le tableau (je suppose également ici, à partir de l'erreur du compilateur, que ce lengthn'est pas une constante de temps de compilation).

Vous devez initialiser manuellement cette baie:

int boardAux[length][length];
memset( boardAux, 0, length*length*sizeof(int) );
David Rodríguez - Dribeas
la source
Je peux également utiliser à cette fin malloc, qu'en est-il de la deuxième question, je l'ai écrite après la réponse de Pavel
bonjourWorld
@helloWorld: Avec les tableaux alloués à la pile, se printf( "%d", boardAux[1][2] )compile correctement . Le compilateur connaît les tailles et sait à quelle position en mémoire se trouve le (1,2) -ème élément. Si vous utilisez l'allocation dynamique, le tableau est unidimensionnel et vous devez effectuer le calcul vous-même:printf("%d", boardAux[ 1*length + 2 ])
David Rodríguez - dribeas
@AndreyT: Merci d'avoir signalé l'erreur dans l' memsetappel. Je viens de le corriger.
David Rodríguez - dribeas
Pourquoi est-ce que j'obtiens cette erreur dans le compilateur C99 lorsque je définis le lengthcomme étant static? En C ++ 14, cela fonctionne très bien.
Muhamed Cicak
26

Vous recevez cette erreur car en langage C, vous n'êtes pas autorisé à utiliser des initialiseurs avec des tableaux de longueur variable. Le message d'erreur que vous recevez dit tout.

6.7.8 Initialisation

...

3 Le type d'entité à initialiser doit être un tableau de taille inconnue ou un type d'objet qui n'est pas un type de tableau de longueur variable.

Fourmi
la source
où avez-vous trouvé cela, pouvez-vous me donner un lien?
helloWorld
1
@helloWorld: Ceci provient du standard de langue (C99). Vous pouvez obtenir une copie "de travail" avec les mises à jour TC3 ici open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
AnT le
5
Il y a des sujets pour lesquels certains ne vous croiront toujours pas si vous ne fournissez que l'explication informelle. Les tableaux de longueur variable sont l'un de ces sujets. +1 pour citer la norme.
Pascal Cuoq
15

Cela donne une erreur:

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

Cela donne également une erreur:

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

Mais cela fonctionne bien:

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

Vous devez mettre de la valeur de la manière suivante:

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

Après avoir déclaré le tableau

int boardAux[length][length];

la façon la plus simple d'affecter les valeurs initiales comme zéro est d'utiliser la boucle for, même si elle peut être un peu longue

int i, j;
for (i = 0; i<length; i++)
{
    for (j = 0; j<length; j++)
        boardAux[i][j] = 0;
}
Krishna Shrestha
la source
2
memsetest plus simple et plus rapide.
Cacahuete Frito
1

La question est déjà répondue mais je voulais souligner une autre solution qui est rapide et fonctionne si la longueur n'est pas censée être modifiée au moment de l'exécution. Utilisez la macro #define avant main () pour définir la longueur et dans main () votre initialisation fonctionnera:

#define length 10

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

Les macros sont exécutées avant la compilation réelle et la longueur sera une constante au moment de la compilation (comme indiqué par David Rodríguez dans sa réponse). Il remplacera en fait la longueur par 10 avant la compilation.

Sergey
la source
0

Déclarez simplement la longueur comme étant un inconvénient, si ce n'est pas le cas, vous devriez allouer de la mémoire dynamiquement

Azizou
la source
2
Je pense que vous devez rechercher ce que signifie const!
Holger le
@Holger: Êtes-vous sûr? Si la variable qui contient la longueur (pas le tableau lui-même, mais la longueur du tableau) est une constante, alors le compilateur connaît la longueur à utiliser pour initialiser le tableau. Par exemple, "int length = 5; int array [length];" donne l'erreur mais " const int length = 5; int array [length];" compile très bien.
Casey le
@Casey: mais const int lenght=5; int array[length][length] = {{0}};pas.
MestreLion
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;
}
Vol de code
la source
1
Bienvenue dans Stack Overflow! Veuillez lire le guide sur la façon d'écrire une bonne réponse: stackoverflow.com/help/how-to-answer Votre réponse actuelle semble vague et n'a aucune explication
gybandi
-5

Pour une déclaration et une initialisation séparées en C ++ comme ceci.

int a[n][m] ;
a[n][m]= {0};
Munawir
la source
1
Pas une question C ++
Cacahuete Frito
Ci-dessus initialise uniquement A [n] [m], pas le tableau entier. int a [n] [m]; memset (a, 0, (n m sizeof (int)); // effacer le mem du tableau La plupart des compilateurs permettent ceci: int a [n] [m] = {0}; // initialise tous les membres à 0
Chris Reid
-9

Tu ne peux pas le faire. Le compilateur C ne peut pas faire une chose aussi complexe sur la pile.

Vous devez utiliser le tas et l'allocation dynamique.

Ce que vous devez vraiment faire:

  • calculer la taille (n m sizeof (élément)) de la mémoire dont vous avez besoin
  • appelez malloc (size) pour allouer la mémoire
  • créer un accesseur: int * access (ptr, x, y, rowSize) {return ptr + y * rowSize + x; }

Utilisez * access (boardAux, x, y, size) = 42 pour interagir avec la matrice.

Pavel Radzivilovsky
la source
une autre question, pourquoi est-ce que je reçois une erreur d'utilisation invalide du tableau avec des limites non spécifiées? printf ("% d", carte [i] [j]);
helloWorld le
10
-1 C99 permet une allocation dynamique dans la pile en tant que code utilisateur (hors initialisation). Il n'est pas nécessaire d'effectuer des allocations dynamiques.
David Rodríguez - dribeas
@helloWorld car les dimensions du tableau doivent être connues.
Pavel Radzivilovsky