Je répondais à cette question, mais lorsque j’ai testé le code suivant, j’ai été dérouté.
#include using namespace std; int main() { int **ptr; int arr[3][3]; ptr =(int **) arr; for (int i=0;i<3;i++){ for (int j=0;j<3;j++){ cout << &arr[i][j] << " =? "; cout << &(ptr[i][j]) << endl; } } return 0; }
Mais je reçois cette sortie:
0x7fff5700279c =? 0 0x7fff570027a0 =? 0x4 0x7fff570027a4 =? 0x8 0x7fff570027a8 =? 0 0x7fff570027ac =? 0x4 0x7fff570027b0 =? 0x8 0x7fff570027b4 =? 0 0x7fff570027b8 =? 0x4 0x7fff570027bc =? 0x8
Pourquoi ne sont-ils pas les mêmes?
int **ptr
et un int arr[3][3]
sont différents, puisque:
----------------------------------- | C | Maths | ----------------------------------- | ptr + 1 | ptr + sizeof(int*) | ----------------------------------- | arr + 1 | arr + 3 * sizeof(int*) | -----------------------------------
Donc, vous n’obtiendrez pas du tout les mêmes résultats (en outre, ptr
et arr
peuvent ne pas avoir la même représentation en mémoire).
int (*ptr)[3] = arr;
fonctionnera, puisque seule la première dimension de l’ arr
se désintègre en un pointeur.
ptr =(int **) arr;
C’est très mauvais – cela implique une reinterpret_cast
et conduit à un comportement indéfini. Les deux types – un int[3][3]
et un int**
– sont complètement incompatibles en termes de disposition de la mémoire.
Un tableau 2D 3-en-3 est un bloc de mémoire contigu qui ressemble à ceci:
0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2 ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐ │ int │ int │ int │ int │ int │ int │ int │ int │ int │ └─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘
Un pointeur vers un pointeur sur int
où chaque pointeur pointe sur le premier élément d’un tableau ressemble à ceci:
┌─────┐ │ │ // The int** └──╂──┘ ┃ ▼ ┌─────┬─────┬┄ │ │ │ // An array of int* └──╂──┴──╂──┴┄ ┃ ┗━━━━━━━━━━┓ ▼ ▼ ┌─────┬─────┬┄ ┌─────┬─────┬┄ │ int │ int │ │ int │ int │ // Arrays of ints └─────┴─────┴┄ └─────┴─────┴┄ 0,0 0,1 1,0 1,1
Cela implique deux niveaux d’indirection. Le type de tableau 2D n’a pas le tableau de pointeurs à parcourir. De plus, les tableaux d’ int
s dans ce cas ne sont pas nécessairement contigus.
Alors pensez à ptr[0]
, par exemple. Quel est le type de l’expression? Puisque ptr
est un int**
, le type de ptr[0]
est un int*
. Cependant, qu’est-ce qui se trouve réellement à l’emplacement ptr[0]
? Pas un pointeur du tout! Au lieu de cela, il y a un tableau d’ int
s.
int ** est un pointeur sur un pointeur sur int. Ce qui signifie qu’il fait référence à un tableau de pointeurs. Cependant, int [x] [y] est un tableau d’entiers x de taille y. C’est un bloc de mémoire unique organisé en x rangées de colonnes y (si vous voulez bien le penser de cette façon.
Pour obtenir ce que vous voulez, vous devez collecter les adresses des colonnes et les stocker dans les lignes de votre pointeur int **.
int arry[3][3]; int** ptr = malloc( sizeof(int*) * 3 ); for( int i = 0; i < 3; i++ ) ptr[i] = arry[i]; for( int i = 0; i < 3; i++ ) for( int j = 0; j < 3; j++ ) printf( "%d -> %d\n", arry[i][j], ptr[i][j]; free( ptr );