Pourquoi int ** ptr ne pointe-t-il pas à la même adresse que int arr lors de l’access à ptr ?

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 );