Comment le pointeur des tableaux multidimensionnels fonctionne-t-il en C

J’expérimente le concept de pointeur sur un tableau multidimensionnel en C. Supposons que je veuille traiter un tableau multidimensionnel via une fonction. Le code ressemble un peu à ceci:

#include  void proc_arr(int ***array) { // some code } int main(int argc, char **argv) { int array[10][10]; for(int i = 0; i < 10; i++) { for(int j = 0; j < 10; j++) { array[i][j] = i * j; } } proc_arr(&array); return 0; } 

Le problème est que, lorsque je veux accéder au array dans proc_arr , je ne peux pas. De ma compréhension, nous devrions y accéder de cette façon:

 void proc_arr(int ***array) { (*array)[0][1] = 10; } 

Donc, je déréverse le array pour dire au compilateur que je veux aller à cette adresse et obtenir la valeur. Mais de toute façon, il se bloque. J’ai essayé plusieurs combinaisons de * et de parenthèses et je ne peux toujours pas le faire fonctionner. Je suis presque sûr que c’est parce que je ne comprends pas les pointeurs et les pointeurs des pointeurs.

Oh, et j’ai remarqué que c’est différent si nous travaillons avec un char ** (tableau de chaîne) aussi, comme pour argv et envp. Mais pour envp, je peux en quelque sorte y accéder avec (*envp) . Pourquoi?

Voici la fonction qui procp envp (et travaillé):

 int envplen(char ***envp) { int count = 0; while((*envp)[count] != NULL) { count++; } return count; } 

Aussi, puis-je accéder d’une manière ou d’une autre à envp dans la fonction envplen avec seulement envp , mais le transmettre quand même par référence?

Merci avant.

Le problème vient du fait que le int array[10][10] alloué sur la stack ne dispose pas de la mémoire de la manière que vous pensez. En effet, les tableaux ne sont pas des pointeurs . La mémoire est toujours disposée dans un tableau linéaire, pas un tableau “à deux dimensions”, même si c’est ce que les indices pourraient indiquer. En d’autres termes, la mémoire de la int array[10][10] se présente comme suit:

 starting address: ending address: | Block_1 of 10 int | Block_2 of 10 int | ... | Block_10 of 10 int | 

Ainsi, lorsque vous convertissez implicitement le tableau en int*** , puis tentez d’accéder au tableau tel que (* array) [1] [10], cela se traduit par quelque chose comme *(*((*array) + 1) + 10) , et la structure de la mémoire pour une telle opération veut voir la configuration de la mémoire comme suit:

 int*** array | | | Pointer | | | | Pointer_0 | Pointer_1 | ... | Pointer 10 | | | | | | | Block of 10 int | | | | | Block of 10 int | | |Block of 10 int| 

Vous avez une incompatibilité de type. Étant donné la déclaration int array[10][10] , le type de l’expression &array sera int (*)[10][10] , pas int *** . Si vous modifiez le prototype de votre fonction pour le lire

 void proc_arr(int (*array)[10][10]) 

alors votre code devrait fonctionner comme écrit.

Le tableau suivant montre les types de différentes expressions de tableau à partir d’une déclaration particulière.

 Déclaration: T a [M]; 

 Le type d'expression se désintègre en        
 ---------- ---- ---------        
          un T [M] T *              
         &au m]                   

         *à                           
       un [i] t                           

 Déclaration: T [M] [N]; 

 Le type d'expression se désintègre en        
 ---------- ---- ---------        
          un T [M] [N] T (*) [N]         
         & a T (*) [M] [N]
         * a T [N] T *
        a [i] T [N] T *
       & a [i] T (*) [N]
       * a [i] T 
     a [i] [j] T

 Déclaration: T [M] [N] [O]; 

 Le type d'expression se désintègre en        
 ---------- ---- ---------        
          a T [M] [N] [O] T (*) [N] [O]
         & a T (*) [M] [N] [O]     
         * a T [N] [O] T (*) [O]
       a [i] T [N] [O] T (*) [O]
      & a [i] T (*) [N] [O]     
      * a [i] T [N] T *
    a [i] [j] T [N] T *
   & a [i] [j] T (*) [N]
   * a [i] [j] T
 a [i] [j] [k] T

Le modèle pour les tableaux de dimension supérieure doit être clair.

Cela ne fonctionnera pas:

 void proc_arr(int ***array) { (*array)[0][1] = 10; } 

Parce que, en coulisse, le compilateur devra changer ceci en un décalage dans la mémoire par rapport au début du tableau. Cela signifie qu’il doit connaître les dimensions du tableau. Vous n’avez pas déclaré ceux-ci dans la signature de la fonction.