Allocation dynamic de tableau sur stack en C

Je viens de faire une expérience hier, et trouve quelque chose de déroutant:

#include  int main() { int j; scanf("%d",&j); const int i = j; int arr[i]; return 0; } 

Le nombre j est lu à partir du clavier et est utilisé pour allouer le tableau arr sur la stack.

Le compilateur ne sait même pas la taille du tableau au moment de la compilation (initialise j à 0?), Mais il n’y a pas d’erreur de compilation. Comment est-ce possible?

Des tableaux de longueur variable ont été ajoutés à C99. C’est décrit dans la justification du C99:

6.7.5.2 Déclarateurs de tableau

C99 ajoute un nouveau type de tableau appelé type de tableau de longueur variable. L’incapacité de déclarer des tableaux dont la taille n’est connue qu’au moment de l’exécution a souvent été invoquée comme moyen de dissuasion principal de l’utilisation de C en tant que langage informatique numérique. L’adoption d’une certaine notion standard de tableaux de temps d’exécution a été jugée cruciale pour l’acceptation de C dans le monde de l’informatique numérique.

Le nombre d’éléments spécifiés dans la déclaration d’un type de tableau de longueur variable est une expression d’exécution. Avant C99, cette expression de taille devait être une expression constante entière.

Il n’y a pas “allocation de tableau dynamic sur la stack”. La taille du tableau doit être spécifiée lors de la déclaration.

Certains compilateurs, tels que GCC, les autorisent comme extension en mode C90 (en GCC, cela équivaut au mode ansi et C89) et en C ++. Dans ce cas, vous recevrez un avertissement ( -Wpedantic ) ou une erreur ( -Werror ou -pedantic-errors ). Consultez la documentation de votre compilateur.

Selon le commentaire de @ Deduplicator, vous semblez avoir une idée fausse. Les tableaux de longueur variable ne peuvent pas être déclarés statiques.

§ 6.7.6.2

10 EXAMPLE 4 Toutes les déclarations de types modifiés de manière variable (VM) doivent être à la scope du bloc ou du prototype de la fonction. Les objects de tableau déclarés avec le _Thread_local , static ou extern storage-class ne peuvent pas avoir un type de tableau de longueur variable (VLA). Toutefois, un object déclaré avec le spécificateur de classe de stockage static peut avoir un type de machine virtuelle (c’est-à-dire un pointeur sur un type de VLA). Enfin, tous les identifiants déclarés avec un type de VM doivent être des identifiants ordinaires et ne peuvent donc pas être des membres ostructures ou unions.

Cela signifie que stockage static et stockage automatic s’excluent mutuellement.

Pour plus de détails sur l’allocation d’une quantité variable de mémoire sur la stack, reportez-vous à la section suivante: Comment un compilateur peut-il implémenter la fonction alloca() (non normalisée) :

Mise en œuvre Alloca

La norme C99 propose des tableaux à longueur variable (“VLA”) avec essentiellement les mêmes fonctionnalités; bien que la mémoire soit récupérée pour chaque étendue plutôt que pour chaque fonction:

Quelle est la différence entre alloca (n) et char x [n]?

Il y a des raisons pour être hésitant à utiliser soit de manière trop agressive avec une taille illimitée. Il n’y a aucun moyen de vérifier si la mémoire de stack est disponible, vous pouvez également vérifier si la mémoire de tas est disponible via. NULL de malloc() . Si votre tableau de longueur variable est trop grand, cela provoquera un débordement de stack et un comportement non défini . vrai pour les deux méthodes d’allocation de stack:

Pourquoi l’utilisation de alloca () n’est-elle pas considérée comme une bonne pratique?

C a une caractéristique telle que les tableaux de longueur variable. Les tableaux avec durée de stockage automatique peuvent être définis dans le vol.