Partage
  • Partager sur Facebook
  • Partager sur Twitter

Allocation dynamique d'un tableau à 2 dimensions

    9 janvier 2022 à 16:20:28

    Bonjour,

    Je souhaite pour un petit programme allouer dynamiquement de la mémoire à un tableau d'entier.

    Je me suis bien cassé la tête, j'ai fait quelques recherches sur internet et je suis tombé sur ça:

    int *tableau;
    int nbColonnes = 5;
    int nbLignes = 10 for(int i = 0; i < nbLignes; i++) { tableau[i] = malloc(sizeof(int) * nbColonnes); }

    C'est ce que j'ai fait, mais le problème c'est que quand j'ai voulu assigner des valeurs grâce à une double-boucle comme ça:

    for(int i = 0; i < nbLignes; i++)
    {
       for(int j = 0; j < nbColonnes; j++)
       {
          tableau[i][j] = //La valeur que mon programme lis dans un fichier
       }
    }

    Mais mon IDE m'a dit " l'expression doit avoir un type pointeur vers objet mais elle a le type int".

    Alors pour l'allocation j'ai essayé ça:

    for (int i = 0; i < nbLignes; i++)
    {
    		for (int j = 0; j < nbColonnes; j++)
    		{
    			map[i][j] = malloc(sizeof(int));
    		}
    }

    Mais j'avais la même erreur cette fois sur le j de l'instruction

    map[i][j] = malloc(sizeof(int));

    .

    Alors je n'aurai qu'une seule question: Comment je fais pour allouer de la mémoire à ce tableau?

    Merci d'avance pour votre réponse.




    • Partager sur Facebook
    • Partager sur Twitter
      9 janvier 2022 à 16:50:38

      SniffierPond a écrit:

      Je me suis bien cassé la tête, j'ai fait quelques recherches sur internet et je suis tombé sur ça: ...

      Mauvaise pioche !

      Pour créer un tableau de tableau (tableau 2D) sur le tas avec malloc, il faut partir sur un pointeur de pointeur  (tableau de tableau d'entier int) :

      int **ptab;

      Ensuite allouer un tableau de pointeur et affecter l'adresse de ce tableau à ptab  (ex : tableau de 5 pointeur sur int) :

      ptab = malloc(5 * sizeof(int*));

      Ensuite allouer pour chaque pointeur du tableau précédent un tableau d'entier (ex : tableau de 10 int) :

      for(int i=0; i<5; i++) ptab[i] = malloc(10 * sizeof(int));

      Au final tu as donc un tableau de 5 tableaux de 10 int.

      -
      Edité par rouIoude 9 janvier 2022 à 16:52:42

      • Partager sur Facebook
      • Partager sur Twitter
      ...
        9 janvier 2022 à 18:02:44

        j'insiste sur ce que rouIoude a dit
        + on alloue un tableau de pointeurs, d'où le  sizeof(int *)  avec le '*'
        + on alloue de l'espace pour des int, d'où le  sizeof(int)  sans le '*'
        • Partager sur Facebook
        • Partager sur Twitter

        Le Tout est souvent plus grand que la somme de ses parties.

          9 janvier 2022 à 21:37:32

          On l'a vu, la manière "simple" de créer un tableau à 2 dimensions, il utilise int**ptab qui pointe sur un tableau de pointeurs, chaque pointeur pointant sur un tableau d'int.
          Si la seconde dimension du tableau est une constante, on a plus simple en utilisant int (*ptab)[5] qui ne nécessite qu'un malloc( nb_lignes * sizeof(int[5]) ).
          Sinon on peut utiliser la linéarisation. On crée un tableau de nb_colonnes*nb_lignes entiers en utilisant int* ptab qui s'initialise par malloc( nb_lignes * nb_colonnes * sizeof(int) ). Malheureusement contrairement aux 2 précédents qui s'utilisent en faisant ptab[i][j], celui-ci doit s'utiliser en faisant ptab[j*nb_colonnes+i]. Ce tableau n'a qu'une dimension mais permet d'émuler un tableau à 2 dimensions

          Pour comprendre ces 3 manières, il suffit de les dessiner.

          • Partager sur Facebook
          • Partager sur Twitter

          En recherche d'emploi.

            10 janvier 2022 à 1:58:07

            @Dalfab a écrit:
            > Si la seconde dimension du tableau est une constante, on a plus simple en utilisant int (*ptab)[5] qui ne nécessite qu'un malloc( nb_lignes * sizeof(int[5])
            OK je fais:
            int *tab = malloc(nbLignes * sizeof(int[5]));
            Je n'ai pas de problème avec ça, mais comment j'écris l'équivalent de tab[i][j] ?
            • Partager sur Facebook
            • Partager sur Twitter

            Le Tout est souvent plus grand que la somme de ses parties.

              10 janvier 2022 à 10:09:08

              PierrotLeFou a écrit:

              mais comment j'écris l'équivalent de tab[i][j] ?

              Et bien : tab[i][j] 

              • Partager sur Facebook
              • Partager sur Twitter
              ...
                10 janvier 2022 à 12:01:21

                Ca m'a l'air assez complexe mais j'ai compris le principe. Je vais essayer. Et du coup si on veut un tableau à trois dimensions il faut un tableau de pointeurs de pointeurs de pointeurs auxquels on affecte chacun un tableau de pointeurs de pointeurs auxquels on affecte chacun un tableau de pointeurs auxquels on affecte chacun une variable allouée dynamiquement?

                Par contre j'ai essayé de décrire la taille du tableau par une constante préprocesseur et mon IDE m'a mis l'erreur "']' attendu" que je ne comprend pas puisque j'ai écrit mon instructions comme ça:

                int* tableau[NB_COLONNES_TABLEAU_MAP];

                -
                Edité par SniffierPond 10 janvier 2022 à 12:43:54

                • Partager sur Facebook
                • Partager sur Twitter
                  10 janvier 2022 à 13:20:09

                  On peut voir la définition de la constante préprocesseur ?

                  Tu as eu plusieurs solutions, alors attention à ne pas mélanger les solutions. Je t'ai donné celle qu'on voit souvent en premier. (ton discours et ton code semble être deux solutions différentes).

                  Ton code correspond à la première solution de dalfab.

                  Ne fait qu'une seule chose à la fois.

                  Commence déjà avec le tableau à 2 dimensions, après on verra ! 

                  -
                  Edité par rouIoude 10 janvier 2022 à 13:28:05

                  • Partager sur Facebook
                  • Partager sur Twitter
                  ...
                    10 janvier 2022 à 13:32:29

                    C'est bien comme ça qu'il faut faire?

                    for (int i = 0; i < nbLignes; i++)
                    		{
                    			int* tableau[NB_COLONNES]; 
                    			map[i] = tableau;
                    
                    			for (int j = 0; j < NB_COLONNES; j++)
                    			{
                    				map[i][j] = malloc(sizeof(int));
                    			}
                    		}

                    La définition de ma constante:

                    #define NB_COLONNES 5;




                    • Partager sur Facebook
                    • Partager sur Twitter
                      10 janvier 2022 à 14:14:21

                      SniffierPond a écrit:

                      La définition de ma constante:

                      #define NB_COLONNES 5;

                      C'est bien ce que je craignais ! Il ne faut pas de point virgule après la définition d'une constante define !

                      SniffierPond a écrit:

                      C'est bien comme ça qu'il faut faire?

                      Non, pas du tout ! Là tu es en train de faire un gros mélange de tout ! 

                      Et c'est quoi map dans ton code ? Poste des code compilable !

                      Sais tu créer un tableau à une dimension avec malloc ?

                      -
                      Edité par rouIoude 10 janvier 2022 à 14:51:26

                      • Partager sur Facebook
                      • Partager sur Twitter
                      ...
                        10 janvier 2022 à 15:17:47

                        Il y a aussi ce sujet relativement récent dans lequel on a discuté de différentes méthodes permettant d'allouer dynamiquement des tableaux à plusieurs dimensions :

                        https://openclassrooms.com/forum/sujet/declaration-dun-tableau-de-pointeurs-avec-malloc

                        • Partager sur Facebook
                        • Partager sur Twitter
                          10 janvier 2022 à 15:28:17

                          Le problème, n'est pas de le faire avec différentes méthodes, mais déjà d'y arriver avec une méthode simple !

                          • Partager sur Facebook
                          • Partager sur Twitter
                          ...
                            10 janvier 2022 à 17:05:38

                            @rouIoude : Pas la peine t'énerver sur moi. Ce qui est simple pour toi ne l'est peut être pas pour d'autres. La méthode que tu indiques est une méthode classique et bien connue, et qui est souvent la première qui vient à l'esprit aux programmeurs C parce qu'on l'a vue tellement de fois dans les centaines de codes qui font traditionnellement comme cela depuis que le C existe.

                            Cependant, je ne la qualifierais pas de simple personnellement (c'est une opinion, on n'est pas obligés d'être d'accord).

                            En tout état de cause, le lien vers le fil précédent donne du code de programmes illustratifs en exemples pour ta méthode et d'autres, y compris celles rappelées par Dalfab ci-dessus, ce que personne n'a fait pour le moment sur ce fil.

                            -
                            Edité par Dlks 10 janvier 2022 à 17:07:52

                            • Partager sur Facebook
                            • Partager sur Twitter
                              10 janvier 2022 à 17:45:51

                              Si je reprend la suggestion de Dalfab:
                              -
                              #include <stdio.h>
                              #include <stdlib.h>
                              int main(void) {
                                  int n=4;
                                  int *tab = malloc(n*sizeof(int[5]));
                                  tab[3][2] = 333;
                              }
                              -
                              J'obtiens:
                              ak.c: In function 'main':                                                                                               
                              ak.c:6:11: error: subscripted value is neither array nor pointer nor vector                                             
                                  6 |     tab[3][2] = 333;                                                                                            
                                    |           ^
                              • Partager sur Facebook
                              • Partager sur Twitter

                              Le Tout est souvent plus grand que la somme de ses parties.

                                10 janvier 2022 à 18:03:11

                                @pierrot: ce code ne génère aucune erreur:
                                 #include <stdlib.h>
                                 
                                 int main(void) {
                                	 int nlines=10;
                                	 int (*ptab)[5];
                                	 ptab=malloc(nlines*sizeof(int[5]) );
                                	 
                                	 ptab[9][4]=0;
                                	 
                                	 return(0);
                                 }
                                • Partager sur Facebook
                                • Partager sur Twitter

                                On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

                                  10 janvier 2022 à 18:05:39

                                  C'est ça qu'il a voulu dire dalfab :

                                  #include <stdio.h>
                                  #include <stdlib.h>
                                  
                                  int main(void) {
                                      int n=4;
                                      int (*tab)[5] = malloc(n*sizeof(int[5]));
                                      tab[3][2] = 333;
                                  }
                                  



                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                  ...
                                    10 janvier 2022 à 18:24:58

                                    Merci rouIoude. Je ne connaissais pas cette forme. Ça fonctionne effectivement. :)

                                    -
                                    Edité par PierrotLeFou 10 janvier 2022 à 18:25:50

                                    • Partager sur Facebook
                                    • Partager sur Twitter

                                    Le Tout est souvent plus grand que la somme de ses parties.

                                      10 janvier 2022 à 18:31:49

                                      Après cette forme fait que l'une des dimensions n'est pas "dynamique" puisqu'elle est fixé dans le code.
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                      ...
                                        10 janvier 2022 à 18:49:27

                                        C'est bien ce que j'avais compris. C'est tout de même une variante utile.
                                        • Partager sur Facebook
                                        • Partager sur Twitter

                                        Le Tout est souvent plus grand que la somme de ses parties.

                                          10 janvier 2022 à 19:29:41

                                          Salut,

                                          Cela peut se faire avec une variable avec la notation VLA et un compilateur C99 comme illustré par cet exemple :

                                          #include <stdio.h>
                                          #include <stdlib.h>
                                          
                                          int main(void)
                                          {
                                          	size_t colonnes = 5;
                                          	size_t lignes = 10;
                                          	int truc = 0;
                                          
                                          	int (*tableau2D_dyn)[colonnes] = malloc(lignes * sizeof(*tableau2D_dyn));
                                          	for (size_t i = 0; i < lignes; i++)
                                          		for (size_t j = 0; j < colonnes; j++)
                                          			tableau2D_dyn[i][j] = truc++;
                                          
                                          	/* faire quelque chose avec le tableau */
                                          
                                          	free(tableau2D_dyn);
                                          
                                          	return 0;
                                          }
                                          

                                          cela permet de passer ce tableau à une fonction void print_array(size_t lignes, size_t colonnes, int array[][colonnes]); comme illustré dans cet autre fil auquel je me référais, qui fonctionnera de la même manière en C99 que le tableau 2D soit alloué dynamiquement ou statiquement et quelle que soit la dimension du tableau car on alloue une mémoire contiguë.

                                          Dire que cette méthode est moins "simple" que de faire 11 malloc et autant de free en obtenant un tableau dont le contenu est dispersé et non contigu en mémoire et qui nécessitera un prototype différent pour être traité avec une fonction par rapport à un tableau 2D en dur est débattable, alors qu'il existe des moyens plus modernes de faire autrement et en une seule allocation.

                                          Enfin, encore une fois, c'est une opinion, et on n'est pas obligés d'être d'accord.

                                          -
                                          Edité par Dlks 10 janvier 2022 à 19:42:44

                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            10 janvier 2022 à 19:58:45

                                            Effectivement le VLA est encore plus simple :

                                            #include <stdio.h>
                                            
                                            int main(void)
                                            {
                                                int x=4;
                                                int y=5;
                                            
                                                int tab[x][y];
                                                
                                                return 0;
                                            }

                                            Mais, ce n'est peut-être pas ce que recherche le PO.

                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                            ...
                                              10 janvier 2022 à 22:49:33

                                              Quitte à utiliser une notation vla :

                                              #include <stdio.h>
                                              #include <stdlib.h>
                                              
                                              void init(size_t row, size_t col, int (*array)[row][col]);
                                              void print(size_t row, size_t col, int (*array)[row][col]);
                                              
                                              int main(void)
                                              {
                                                  size_t col=3;
                                                  size_t row=2;
                                                  int (*array)[row][col] = malloc(sizeof *array);
                                              
                                                  init(row, col, array);
                                                  print(row, col, array);
                                              
                                                  free(array);
                                              
                                                  return 0;
                                              }
                                              
                                              void init(size_t row, size_t col, int (*array)[row][col])
                                              {
                                                  for(size_t r=0; r<row; r++)
                                                      for(size_t c=0; c<col; c++) {
                                                          (*array)[r][c]=r+c;
                                                      }
                                              }
                                              
                                              void print(size_t row, size_t col, int (*array)[row][col])
                                              {
                                                  printf("array : int[%zu][%zu]\n", row, col);
                                                  for(size_t r=0; r<row; r++) {
                                                      for(size_t c=0; c<col; c++) {
                                                          printf("%d ", (*array)[r][c]);
                                                      }
                                                      putchar('\n');
                                                  }
                                              }
                                              

                                              qui donne :

                                               $ gcc -g -Wall -Wextra -o vla vla.c
                                               $ valgrind --leak-check=full --track-origins=yes --show-reachable=yes ./vla
                                              ==117321== Memcheck, a memory error detector
                                              ==117321== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
                                              ==117321== Using Valgrind-3.17.0 and LibVEX; rerun with -h for copyright info
                                              ==117321== Command: ./vla
                                              ==117321== 
                                              array : int[2][3]
                                              0 1 2 
                                              1 2 3 
                                              ==117321== 
                                              ==117321== HEAP SUMMARY:
                                              ==117321==     in use at exit: 0 bytes in 0 blocks
                                              ==117321==   total heap usage: 2 allocs, 2 frees, 1,048 bytes allocated
                                              ==117321== 
                                              ==117321== All heap blocks were freed -- no leaks are possible
                                              ==117321== 
                                              ==117321== For lists of detected and suppressed errors, rerun with: -s
                                              ==117321== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

                                              Ce qui est dommage est que c'est largement inutilisable directement dans une struct par exemple.

                                              Edit: Ce qui est important de remarquer ici est que l'on utilise la notation VLA mais aussi qu'on déclare et définit un vla sur le tas et non la pile … donc a priori moins de souci d'explosion de pile.

                                              Cela se généralise facilement à plusieurs dimensions.

                                              Utiliser cette méthode est un challenge si on veut encapsuler tout ça dans une struct. Il faudrait passer le type du pointeur en void et caster à tire-larigot.

                                              Edit 2: après réflexion, on ne crée pas un VLA sur le tas … on ne fait qu'utiliser la notation VLA.

                                              Edit 3:

                                              Et en poussant le bouchon un peu plus loin …

                                              #include <stdio.h>
                                              #include <stdlib.h>
                                              
                                              void init(size_t row, size_t col, int array[row][col]);
                                              void print(size_t row, size_t col, int array[row][col]);
                                              
                                              int main(void)
                                              {
                                                  size_t row=3;
                                                  size_t col=2;
                                                  int (*array)[col] = malloc( sizeof(int[row][col]) );
                                              
                                                  init(row, col, array);
                                                  print(row, col, array);
                                              
                                                  free(array);
                                                  return 0;
                                              }
                                              
                                              void init(size_t row, size_t col, int array[row][col])
                                              {
                                                  for(size_t r=0; r<row; r++)
                                                      for(size_t c=0; c<col; c++) {
                                                          array[r][c] = r+c;
                                                      }
                                              }
                                              
                                              void print(size_t row, size_t col, int array[row][col])
                                              {
                                                  printf("array : int[%zu][%zu]\n", row, col);
                                                  for(size_t r=0; r<row; r++) {
                                                      for(size_t c=0; c<col; c++) {
                                                          printf("%d ", array[r][c]);
                                                      }
                                                      putchar('\n');
                                                  }
                                              }
                                              

                                              on obtient toujours :

                                              $ gcc -g -Wall -Wextra -o vla2 vla2.c
                                              $ valgrind --leak-check=full --track-origins=yes --show-reachable=yes ./vla2
                                              ==118767== Memcheck, a memory error detector
                                              ==118767== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
                                              ==118767== Using Valgrind-3.17.0 and LibVEX; rerun with -h for copyright info
                                              ==118767== Command: ./vla2
                                              ==118767== 
                                              array : int[3][2]
                                              0 1 
                                              1 2 
                                              2 3 
                                              ==118767== 
                                              ==118767== HEAP SUMMARY:
                                              ==118767==     in use at exit: 0 bytes in 0 blocks
                                              ==118767==   total heap usage: 2 allocs, 2 frees, 1,048 bytes allocated
                                              ==118767== 
                                              ==118767== All heap blocks were freed -- no leaks are possible
                                              ==118767== 
                                              ==118767== For lists of detected and suppressed errors, rerun with: -s
                                              ==118767== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
                                              


                                              Cette dernière version pourrait même être étendue simplement dans une struct avec un membre flexible … ce serait à creuser.


                                              -
                                              Edité par White Crow 10 janvier 2022 à 23:10:44

                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                10 janvier 2022 à 23:13:51

                                                On pourrait simplifier les fonction et envoyer l'adresse du premier élément du tableau :

                                                #include <stdio.h>
                                                #include <stdlib.h>
                                                
                                                void init(size_t row, size_t col, int array[row][col]);
                                                void print(size_t row, size_t col, int array[row][col]);
                                                
                                                int main(void)
                                                {
                                                    size_t col=3;
                                                    size_t row=2;
                                                    int (*array)[row][col] = malloc(sizeof *array);
                                                
                                                    init(row, col, &array[0][0]);
                                                    print(row, col, *array);
                                                
                                                    free(array);
                                                
                                                    return 0;
                                                }
                                                
                                                void init(size_t row, size_t col, int array[row][col])
                                                {
                                                    for(size_t r=0; r<row; r++)
                                                        for(size_t c=0; c<col; c++) {
                                                            array[r][c]=r+c;
                                                        }
                                                }
                                                
                                                void print(size_t row, size_t col, int array[row][col])
                                                {
                                                    printf("array : int[%zu][%zu]\n", row, col);
                                                    for(size_t r=0; r<row; r++) {
                                                        for(size_t c=0; c<col; c++) {
                                                            printf("%d ", array[r][c]);
                                                        }
                                                        putchar('\n');
                                                    }
                                                }


                                                Edit : bon ben je vois que tu y a pensé encore en mieux.

                                                -
                                                Edité par rouIoude 10 janvier 2022 à 23:16:33

                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                ...
                                                  10 janvier 2022 à 23:41:04

                                                  @rouIoude : tu indiques

                                                  > Effectivement le VLA est encore plus simple : (...) Mais, ce n'est peut-être pas ce que recherche le PO.

                                                  Le code que tu postes :

                                                  #include <stdio.h>
                                                   
                                                  int main(void)
                                                  {
                                                      int x=4;
                                                      int y=5;
                                                   
                                                      int tab[x][y];
                                                       
                                                      return 0;
                                                  }

                                                  n'est pas équivalent. Ce code déclare un tableau dans la pile, avec les limitations que cela comporte (la taille de la pile est limitée). Ce programme n'utilise pas du tout le tas. Si tu lances Valgrind dessus, il te confirmera que "total heap usage: 0 allocs, 0 frees, 0 bytes allocated".

                                                  Le code que je propose utilise le tas :

                                                  #include <stdio.h>
                                                  #include <stdlib.h>
                                                   
                                                  int main(void)
                                                  {
                                                      size_t colonnes = 5;
                                                      size_t lignes = 10;
                                                      int truc = 0;
                                                   
                                                      int (*tableau2D_dyn)[colonnes] = malloc(lignes * sizeof(*tableau2D_dyn));
                                                      for (size_t i = 0; i < lignes; i++)
                                                          for (size_t j = 0; j < colonnes; j++)
                                                              tableau2D_dyn[i][j] = truc++;
                                                   
                                                      /* faire quelque chose avec le tableau */
                                                   
                                                      free(tableau2D_dyn);
                                                   
                                                      return 0;
                                                  }

                                                  Valgrind indique : "total heap usage: 1 allocs, 1 frees, 200 bytes allocated".

                                                  Les 50 int composant le tableau tableau2D_dyn (qui tiennent chacun en 4 bytes) sont bien alloués sur le tas.

                                                  -
                                                  Edité par Dlks 10 janvier 2022 à 23:42:20

                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                    11 janvier 2022 à 10:06:25

                                                    tient, il y a de l'écho ^_^

                                                    Sinon l'utilisation d'un membre flexible dans uns structure n'est pas possible avec ce type de tableau. On peut au mieux caster avant l'utilisation, mais cela revient à cacher le calcul d'indice (genre i*width+j) dans le cast et le déréférencement ; ce qui en soi est inutile.

                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                      11 janvier 2022 à 14:18:23

                                                      > tient, il y a de l'écho ^_^

                                                      Tu veux sûrement parler de l'écho que faisait ton post au mien qui le précédait de plusieurs heures... mais rassures toi, je ne me serais pas permis cette réflexion O:-)

                                                      L'utilisation d'un membre flexible est une piste intéressante pour utiliser ces mécanismes en relation avec une struct, où on ne peut pas définir des types VLA.

                                                      Pour le membre flexible de struct, j'ai commis ceci :

                                                      #include <stdio.h>
                                                      #include <stdlib.h>
                                                      
                                                      struct dyn_thing {
                                                              size_t col;
                                                              size_t lig;
                                                              int t2D[];
                                                      };
                                                      
                                                      int main(void)
                                                      {
                                                              size_t col = 5;
                                                              size_t lig = 10;
                                                              int truc = 0;
                                                      
                                                              struct dyn_thing  * dt = malloc(sizeof(*dt) + sizeof(int) * col * lig);
                                                              dt->col = col;
                                                              dt->lig = lig;
                                                              int (*t2D)[col] = (void *)dt->t2D;
                                                      
                                                              for (size_t i = 0; i < lig; i++)
                                                                      for (size_t j = 0; j < col; j++)
                                                                              t2D[i][j] = truc++;
                                                      
                                                              free(dt);
                                                      
                                                              return 0;
                                                      }
                                                      

                                                      La ligne 19 pourrait être remplacée par une macro appelée juste comme make2D(t2D, dt) qui permette d'utiliser t2D ensuite dans la fonction avec la notation [][].

                                                      Cela fonctionne en C99, qui a introduit le membre flexible de struct outre les VLA et la possibilité d'affecter des types pointeurs sur VLA qui sont modifiables à l'exécution.

                                                      Le membre flexible doit être la fin de la struct, ce qui signifie qu'il ne peut y en avoir qu'un.

                                                      Avec gcc Valgrind ne bronche pas sur ce code.

                                                      $ gcc -g -Wall -Werror temp.c 
                                                      $ valgrind ./a.out
                                                      ==12525== Memcheck, a memory error detector
                                                      ==12525== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
                                                      ==12525== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
                                                      ==12525== Command: ./a.out
                                                      ==12525== 
                                                      ==12525== 
                                                      ==12525== HEAP SUMMARY:
                                                      ==12525==     in use at exit: 0 bytes in 0 blocks
                                                      ==12525==   total heap usage: 1 allocs, 1 frees, 216 bytes allocated
                                                      ==12525== 
                                                      ==12525== All heap blocks were freed -- no leaks are possible
                                                      ==12525== 
                                                      ==12525== For counts of detected and suppressed errors, rerun with: -v
                                                      ==12525== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
                                                      

                                                      -
                                                      Edité par Dlks 11 janvier 2022 à 14:23:05

                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                        11 janvier 2022 à 14:23:33

                                                        En effet j'avais testé un truc très similaire, les grands esprits se rencontrent dit-on

                                                        #include <stdio.h>
                                                        #include <stdlib.h>
                                                        #include <string.h>
                                                        
                                                        struct darr {
                                                            size_t row;
                                                            size_t col;
                                                            int data[];
                                                        };
                                                        
                                                        struct darr *darr_new(size_t row, size_t col);
                                                        void darr_free(struct darr *darr);
                                                        
                                                        void darr_init(struct darr *darr);
                                                        void darr_print(struct darr *darr);
                                                        
                                                        int main(void)
                                                        {
                                                            struct darr *d=darr_new(3,2);
                                                            darr_init(d);
                                                            darr_print(d);
                                                            darr_free(d);
                                                        
                                                            return 0;
                                                        }
                                                        
                                                        
                                                        struct darr *darr_new(size_t row, size_t col)
                                                        {
                                                            struct darr *new=malloc( sizeof *new + sizeof(int [row][col]) );
                                                            new->row = row;
                                                            new->col = col;
                                                            memset(new->data, 0, sizeof(int [row][col]));
                                                            return new;
                                                        }
                                                        
                                                        void darr_free(struct darr *darr)
                                                        {
                                                            free(darr);
                                                        }
                                                        
                                                        void darr_init(struct darr *darr)
                                                        {
                                                            for(size_t row=0; row<darr->row; row++)
                                                                for(size_t col=0; col<darr->col; col++) {
                                                                    ((int(*)[darr->col]) darr->data)[row][col]=row+col;
                                                                }
                                                        }
                                                        
                                                        void darr_print(struct darr *darr)
                                                        {
                                                            printf("darr : int %zu × %zu\n", darr->row, darr->col);
                                                            for(size_t row=0; row<darr->row; row++) {
                                                                for(size_t col=0; col<darr->col; col++) {
                                                                    printf("%d ", ((int(*)[darr->col])darr->data)[row][col]);
                                                                }
                                                                putchar('\n');
                                                            }
                                                        }
                                                        

                                                        sans passer par une variable sur le stack … mais du coup comme je le disais, les casts ne sont qu'un ersatz compliqué d'un calcul d'indice … 

                                                        Edit: les editions étant ce qu'elles sont, tu pourras constater tout de même (rien qu'avec la réaction de Rouloude en fait) l'antériorité … bref l'important étant de montrer ce genre de manipulations … je suppose.

                                                        -
                                                        Edité par White Crow 11 janvier 2022 à 14:26:58

                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                          11 janvier 2022 à 19:44:47

                                                          > sans passer par une variable sur le stack … mais du coup comme je le disais, les casts ne sont qu'un ersatz compliqué d'un calcul d'indice …

                                                          Oui, je vois ce que tu veux dire. Cependant, en passant par une variable pointeur VLA qui rétablit la nature souhaitée du type du membre flexible (FAM), on n'a plus qu'à l'utiliser comme un tableau à 2 dimensions et on n'a pas besoin de cast compliqués. C'est fait une fois pour la fonction qui utilise le FAM.

                                                          C'est une technique courante, pour accéder à des parties de struct qui autrement nécessiteraient une syntaxe à rallonge, que d'en simplifier l'accès avec une variable pointeur locale à la fonction.

                                                          Sur les questions d' "écho" et d' "antériorité" je n'en fais pas un fromage (c'est d'ailleurs toi qui les soulève), mais je t'ai fait un MP car je crois qu'il y a un malentendu.

                                                          -
                                                          Edité par Dlks 11 janvier 2022 à 19:54:06

                                                          • Partager sur Facebook
                                                          • Partager sur Twitter
                                                            11 janvier 2022 à 20:58:10

                                                            En effet, et je m'excuse de ce malentendu, my bad.

                                                            • Partager sur Facebook
                                                            • Partager sur Twitter
                                                              12 janvier 2022 à 11:21:07

                                                              Pas de problème White Crow :-)
                                                              • Partager sur Facebook
                                                              • Partager sur Twitter

                                                              Allocation dynamique d'un tableau à 2 dimensions

                                                              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                                              • Editeur
                                                              • Markdown