2017-10-07 9 views
0

tout le monde.C pointeurs de langue: int ** Vs. int (* g) []

j'utiliser Visual Studio 2013 (C++) et définit un tableau 2D de la fonction principale:

int _tmain(int argc, char **argv) 
{ 
    int g[3][3] = { { 1, 2, 3, }, { 4, 5, 6, }, { 7, 8, 9, }, }; 
    ... 

    return 0; 
} 

puis, I définie une fonction dans Définition 1:

Définition 1:

void print_array(int **arr, int kx, int ky) 
{ 
    for (int i = 0; i < kx; i++) { 
     for (int j = 0; j < ky; j++) { 
      printf("%d ", arr[i][j]); 
     } 
     printf("\n"); 
    } 
} 

Je souhaite appeler cette fonction à partir de la fonction principale:

int _tmain(int argc, char **argv) 
{ 
    int g[3][3] = { { 1, 2, 3, }, { 4, 5, 6, }, { 7, 8, 9, }, }; 

    print_array(g, 3, 3); 

    return 0; 
} 

Le studio visuel me dit que:

Error 1 error C2664: 'void print_array(int **,int,int)' : cannot convert argument 1 from 'int [3][3]' to 'int **' 

Je sais aussi une autre méthode de définition:

Define 2

void print_array(int (*arr)[3], int kx, int ky) 
{ 
    for (int i = 0; i < kx; i++) { 
     for (int j = 0; j < ky; j++) { 
      printf("%d ", arr[i][j]); 
     } 
     printf("\n"); 
    } 
} 

Maintenant, cela fonctionne. Ma question est: je me suis souvenu avant qu'ils (Define 1 et Define 2) travaillé à la fois dans le vieux compilateur, nommé vous pouvez passer le nom du tableau comme int ** ou int (*p) [] correctement à une autre fonction. Cependant, dans Visual Studio C++ ce n'est pas le cas. Visual Studio C++ est-il beaucoup plus strict que les autres compilateurs? Ou j'ai fait quelque chose de mal?

Merci beaucoup!

+3

Les tableaux ne sont pas des pointeurs. Les pointeurs ne sont pas des tableaux. – EOF

+0

"* vous pouvez passer le nom du tableau comme int **' ou 'int (* p) []' * "vous n'aviez probablement pas activé ou simplement ignoré les autres avertissements du" * ancien * ". * Ou * votre mémoire vous trompe ... ;-) – alk

+0

Possible duplicate de [Pourquoi ne pouvons-nous pas utiliser le double pointeur pour représenter les tableaux bidimensionnels?] (Https://stackoverflow.com/questions/4470950/why- cant-we-use-double-pointer-à-représenter-two-dimensional-arrays) –

Répondre

6

Je remenbered avant qu'ils (Définir 1 et définir 2) à la fois dans le vieux travaillé compilateur,

Si la mémoire est correcte, l'ancien compilateur a été cassé. Le code n'a jamais été valide C.

Vous pouvez convertir un tableau, int x[3], en un pointeur, int *p, librement. Cela a toujours fonctionné, et il y a beaucoup de cas où cela arrive implicitement.

Cependant, int (*x)[3] est un pointeur et int **y est un pointeur, mais ils pointent vers des types d'objets complètement différents! Vous ne pouvez pas non plus convertir un int * en double *.

Vous pouvez voir que x et y ont une structure différente si vous les dessinez:

+-------------+  +-----+ 
| int (*x)[3] | ----> | int | 
+-------------+  | --- | 
         | int | 
         | --- | 
         | int | 
         +-----+ 
         | ... | 

+---------+  +-------+  +-----+ 
| int **y | ----> | int * | ----> | int | 
+---------+  +-------+  +-----+ 
        | ... |  | ... | 

Ils ne regardent pas la même chose du tout, ont-ils?

+0

Merci! Explication très claire! J'utilise maintenant la seconde méthode: int (*) [] et ça va bien. – zchenkui

0

tableau et la conversion de pointeur ne peut se faire au 1er niveau, de sorte int* et int[] intègrent bien dans l'autre, mais pas int** et int[][].

En fait, int** (peut être converti en int(*)[]) pointe vers un tableau de pointeurs, dont chacun peut pointer vers des emplacements différents, mais évidemment les sous-réseaux d'un réseau 2D ne peut pas. C'est le problème auquel vous êtes confronté.

+3

S'il vous plaît, que voulez-vous exprimer ici: "* peut être converti en int (*) []' * "? – alk

1

Sauf quand il est l'opérande de l'sizeof ou & unaire opérateurs, ou est un littéral chaîne utilisée pour initialiser un tableau de caractères dans une déclaration, l'expression de type « réseau de N éléments de T » seront converties ("Decay") à une expression de type "pointeur vers T", et la valeur de l'expression sera l'adresse du premier élément du tableau.

Lorsque vous appelez print_array(g, 3, 3);, l'expression g est de type « tableau 3 éléments de T », où T est « 3-élément de int ». Donc, g va "décroître" pour taper "pointeur vers T", ou "pointeur vers 3-élément de int", ou int (*)[3]. C'est pourquoi votre deuxième définition fonctionne.

est ici une table à portée de main pour aider à se rappeler certaines de ces règles:

Type   Decays to 
————   ————————— 
T [N]   T * 
T [M][N]  T (*)[N] 
T [L][M][N]  T (*)[M][N] 
+0

Merci John! Cette table est géniale et claire! – zchenkui