Forum Programmation.c langage C : pourquoi on ne peut pas allouer la taille d'un tableau pendant l'exécution du programme?

Posté par  . Licence CC By‑SA.
Étiquettes : aucune
0
12
sept.
2019

bonjour à tous,

si j'ai le code suivant :

void f( int size )
{
    int tab[size];
    ...
}

Le compilateur va retourner une erreur, pourtant en assembleur il est tres facile de réaliser le code ci dessus :
:
push rbp
mov rbp, rsp
sub rsp, eax //avec eax = size

pourquoi en C je ne peux donc pas faire ca. Est ce juste une convention ou alors il y a une raison derriere tout ca ?

Merci d'avance pour vos reponses

  • # Tableau statique

    Posté par  (site web personnel) . Évalué à 2.

    La taille d'un tableau statique doit être connue à la compilation, donc ça ne peut pas dépendre d'un paramètre qui pourrait varier d'un appel à l'autre.

    C'est plutôt malloc (ou autre technique assimilée) que l'on utilisera pour gérer un tableau de taille variable.

    Debian Consultant @ DEBAMAX

    • [^] # Re: Tableau statique

      Posté par  (site web personnel) . Évalué à 5.

      ou utiliser un compilateur C datant de moins de 20 ans supportant le C99 (voir mon commentaire) ^

      • [^] # Re: Tableau statique

        Posté par  . Évalué à 3.

        Il ne s'agit pas seulement du compilateur, mais de tout l'environnement, la toolchain.

        On ne peut pas compiler le noyau linux ou un module en C11 par exemple, même avec GCC8.


        Et n'essayez pas d'introduire une déclaration de variables dans vos boucles, vous allez vous faire engueuler par Linus.

    • [^] # Re: Tableau statique

      Posté par  (Mastodon) . Évalué à 3.

      (ou autre technique assimilée)

      $ man 3 alloca

  • # Les différentes types d'allocation

    Posté par  . Évalué à 2.

    Pour comprendre le problème, il faut savoir qu'il y a 3 types d'allocations de mémoire possibles, cette page wikipedia le décrit assez bien :

    • allocation statique
    • allocation dynamique automatique
    • allocation dynamique manuelle

    Une variable déclarée dans une fonction sera allouée dynamiquement et gérée de façon automatique (déallocation lors de la fin d'exécution du bloc). La question posée est donc, pourquoi est-ce que l'allocation dynamique automatique doit être de taille fixe ?

    Pour le cas d'un tableau, il faut avoir en tête ce qu'est un tableau et en C : c'est un pointeur. L'indice de ton tableau est l'offset du pointeur. Ainsi, pour que l'illusion d'avoir un tableau fonctionne, il faut que les données soient organisées de façon ordonnée dans la mémoire.

    De façon schématique, ça ressemble à ça :

    | tab[0] | tab[1] | … | tab[size-1] |

    Tant qu'il n'y a "rien" derrière ton tableau, tu pourrais l'agrandir mais si une variable vient s'ajouter derrière, le tableau ne pourra plus être agrandi. Comme ces allocations sont gérés dynamiquement, il n'est pas possible de pouvoir garantir l'agrandissement d'un tableau.

    • [^] # Re: Les différentes types d'allocation

      Posté par  (site web personnel) . Évalué à 4.

      C'était vrai avec l'ANSI C, ce n'est plus exact avec le C "d'aujourd'hui" (C99 & +), qui supporte les variables length array dans certaines conditions (pas dans les structures), ou les extensions GCC qui le supportent quasiment partout.

      Après c'est un trade-off en performances qui ne convient pas à Linus pour le kernel par exemple, personnellement je pense que si ses arguments sont surement vrai aujourd'hui ils sont aussi probablement corrigeable, et qu'une facilité et uniformité d'écriture apporte un plus en sécurité mais bon, le kernel est maintenant VLA-free depuis plus d'un an.

  • # C99: Variable Length Array

    Posté par  (site web personnel) . Évalué à 5.

    Alors tu peut le faire et ça marche très bien, si ton compilateur supporte la norme C99 et il y en a un paquet:

    https://godbolt.org/z/BVuDxz
    Ref VLA:
    https://en.wikipedia.org/wiki/Variable-length_array
    https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html

  • # Convention

    Posté par  (Mastodon) . Évalué à 3. Dernière modification le 12 septembre 2019 à 13:38.

    Oui pour moi c'est plutôt une volonté de convention : le tableau est de taille statique point. Apparemment ça a bougé en C99, mais l'idée de base doit être par là.

    Ensuite le C étant quand même assez fun, rien ne t'empêche de faire ton malloc puis d'utiliser le tableau.

    void f( int size )
    {
        int *tab;
    
        tab = malloc(sizeof(int) * size);
    
        tab[0] = 0;
        tab[size-1] = 0;
    }

    Tu as écris le malloc(), tu as donc une chance de penser à écrire le free() :)

    (j'ai même pas compilé ce code, j'espère ne pas dire de grosses conneries !!!)

    En théorie, la théorie et la pratique c'est pareil. En pratique c'est pas vrai.

    • [^] # Re: Convention

      Posté par  . Évalué à 4.

      j'ai même pas compilé ce code, j'espère ne pas dire de grosses connerie

      Ça devrait fonctionner comme ça.
      J'aurais casé un calloc pour que ça fasse encore plus tableau, par contre.

    • [^] # Re: Convention

      Posté par  . Évalué à 3.

      Tu as oublié la désallocation :'(

      • [^] # Re: Convention

        Posté par  (Mastodon) . Évalué à 2.

        Exactement, et en plus j'en parle !

        En théorie, la théorie et la pratique c'est pareil. En pratique c'est pas vrai.

      • [^] # Re: Convention

        Posté par  . Évalué à -1.

        Tu as oublié la désallocation :'(

        Ou pas …

        Sur les systèmes les plus utilisés, dont Linux, la libération sera effectuée de toute façon en sortie de programme.

        Tant que l'allocation est contrôlée, la libération est inutile.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.