10
votes

Pourquoi ne puis-je pas initialiser un tableau de taille variable?

GCC ne donne aucune erreur lorsque vous initialisez un tableau de taille variable tant que la variable est constituée, mais lorsqu'elle n'est pas, elle ne compilera pas.

Quelle est la raison derrière cela? Ce qui est si faux avec faire: xxx

qui ne compilera pas du tout, mais si je n'initialise pas le test [], alors cela compile! Cela n'a aucun sens pour moi, car pour autant que je sache, un cadre de pile doit être conçu pour s'adapter à ce tableau en fonction de sa taille (7 INTS), quoi que ce soit (ce qui signifie que les littéraux entier que j'utilise. Avoir un sens, si je ne me trompe pas), quelle différence cela fait-il si je l'initialise ou non?

Une autre de mes questions de conception Crazy C ++ ...

Merci!


0 commentaires

6 Réponses :


3
votes

Le code n'est pas valide en standard C ++.

Selon (8.3.4.1) de la norme C ++ Standard , Taille du tableau doit être une expression constante

Les tableaux de longueur variable ne sont pas autorisés dans C ++ car C ++ fournit STD :: vecteur pour cela.

La matrice de longueur variable était une fonctionnalité introduite en C99 après la ramification C ++ de la norme C à partir de C98. C ++ a déjà eu std :: vecteur pour fournir des fonctionnalités des tableaux de longueur variable de sorte que C ++ standard ne permettait jamais de disposer de tableaux de longueur variable dans le cadre de la norme.

Si votre compilateur le supporte, il s'agit d'une extension de compilateur. Compilez avec l'option -pedantique et cela vous informera de la même chose avec l'avertissement indiquant qu'il est interdit par ISO C ++


8 commentaires

@Mistersir: convenu - la STL (quel std :: vecteur fait partie de) n'était même pas une partie de la norme originale C ++.


@MisterSIR: J'espère que cela clarifie un peu. C standard permet à VLA (tableaux de longueur variable) C ++ ne le fait pas!


Je ne comprends toujours pas pourquoi avoir une seule fonctionnalité vous oblige à interdire à l'autre. Je veux dire, regarde maloc et nouveau.


@MisterSIR: Simplement, parce que c ++ a vecteur qui est bien meilleur que les tableaux de toute façon.


@Mistersir: Et je ne vois pas quelle partie de la réponse est incorrecte pour être évoquée?


@Als: Il repose presque entièrement sur votre propre hypothèse. Je ne pouvais que la remettre après que vous ayez ajouté la partie sur la norme.


@MisterSIR: VLA en C ++ est un si fréquemment demandé et discuté de la question ici que je pensais que presque tout le monde en est conscient. OH et BTW, ce n'était jamais mon hypothèse que j'avais toujours au courant de cet être dans la norme.


@Als: Je parle de la façon dont vous venez de dire "parce que c ++ a des vecteurs", ce qui n'est qu'une hypothèse.



9
votes
  • La taille de la matrice doit être une expression intégrale constante.
  • Un littéral intégral est une expression intégrale constante. ( int arr [5]; )
  • Une variable intégrale constante initialisée avec une expression constante est une expression constante. ( const int j = 4; const int i = j; int a [i]; )

  • Une variable constante initialisée avec une expression non constante n'est pas une expression constante XXX


6 commentaires

Le code que vous avez posté ne me donne aucune erreur avec GCC du tout. Compile bien; C'est pourquoi je suis tellement confus. Si je change int arr [y]; à int arr [y] = {3, 2}; Je vais avoir une erreur. Différence? Aucune idée.


@MisterSIR: Vous avez oublié de spécifier -pedantic . Sans cela, GCC n'est pas et n'essaie pas d'être une implémentation C ++ conforme. Vous ne pouvez pas conclure que simplement parce que GCC accepte quelque chose, il doit être syntaxiquement correct C ++.


Je vois maintenant .. Donc, vous dites même sans initialiser qu'il est incorrect, mais GCC le permet de toute façon? De plus, la compilation avec -wall et -pedantic ne donne toujours qu'un avertissement, pas une erreur. Si ce que vous dites est vrai et que ce n'est que le choix de design de GCC, je me demande ce qu'ils étaient élevés quand ils l'ont écrit alors.


@MisterSIR: La norme nécessite uniquement que les programmes incorrects soient diagnostiqués par la mise en œuvre, et non qu'ils ne parviennent pas à compiler. Un avertissement est un diagnostic. Si vous souhaitez que des programmes incorrects ne parviennent pas à compiler, utilisez -pedantic-erreurs . Ce n'est pas seulement le choix de conception de GCC, il est pris à partir de C99.


Vous pouvez également utiliser l'option -Std = C ++ 98. Voir GCC.GNU.ORG/ONLINDOCS/GCC / ...


VLS in C ++ est une extension GCC: une caractéristique supplémentaire qu'ils ont décidé de mettre en œuvre même si elle n'est pas dans la norme C ++. Ils l'ont probablement mis en œuvre parce que C99 le fait.



4
votes

Certains compilateurs permettent à ceci si vous utilisez const int si taille = 7; . Théoriquement, le compilateur pourrait comprendre que sa taille est constante mais elle ne le fait pas.


1 commentaires

Certains compilateurs ?! Je pense que tout compilateur C ++ décent doit permettre cela car il est standard!



4
votes

de http://gcc.gnu.org/onlineDocs/gcc/variable -Length.html "Les matrices automatiques de longueur variable sont autorisées dans l'ISO C99 et, comme une extension GCC les accepte en mode C90 et en C ++."

Votre programme n'est pas valide en C ++ et que GCC compile comme «une extension». Vous devrez probablement demander aux auteurs de GCC pourquoi ils ont décidé de mettre en œuvre de cette manière.


2 commentaires

+1 que et la raison probable est que c'est ambigu. Un tableau de taille constante avec une liste d'initialistes initialise autant d'éléments que dans la liste et zéro-initialise le reste. Un tableau sans taille explicite utilise implicitement la longueur de la liste d'initialistes. Et qu'est-ce qu'un tableau avec une longueur de non-const est-il censé faire? Sauf si la longueur non constante est identique à la longueur de la liste d'initialistes, elle pourrait faire soit.


Ce commentaire pointe le marteau droit à la tête de clou.



5
votes

C'est en fait plus comme une question de conception Crazy C99, car les tableaux de longueur variable sont une fonctionnalité de C99 que GCC permet à C ++ comme extension.

en C99, 6.7.8 / 3 indique "Le type de l'entité à initialiser ... n'est pas un type de matrice de longueur variable", de sorte que GCC vient d'utiliser la même règle pour son extension requise par C99.

Le document de Rationalde C99 ne dit rien sur la raison pour laquelle une VLA ne peut pas être initialisée. Je peux spéculer que cela pourrait être dû au risque d'excès d'éléments dans l'initialiseur, si la valeur prévue pour la taille s'avère plus petite que l'initialisateur. Mais je ne sais pas.


2 commentaires

Peut-être que, mais alors c'est juste un problème avec le programmeur et non la langue elle-même (comme je suppose que la plupart des programmeurs savent que s'ils écrivaient une taille Int = 27, la taille d'une arrame sera de 27 éléments ...).


@Mistersir: Bien sûr, mais les VLAS ne sont pas conçues pour que vous écris sans point inutilement intorme int = 27; int arr [taille]; au lieu de int arr [27]; . Ils sont conçus pour que vous puissiez écrire un fonctionnement annulement (intorme int) {int ARRA [taille]; ...} .



0
votes

Je ne suis pas sûr des intentions des concepteurs de GCC lors de la mise en œuvre de cette extension, mais une raison possible pourquoi l'extension GCC fonctionne comme celle-ci est la suivante: xxx pré>

compile sans avertissement, raisonnable à Supposez que l'utilisateur veut {1,0} p> xxx pré>

compile avec un avertissement, que doit le compilateur? P>

int i;
cin >> i;
int is3[i] = {1,2}


0 commentaires