Come altri hanno sottolineato, una matrice multidimensionale è una matrice di matrici, non una matrice di puntatori.
Penso che la causa principale del fraintendimento sia il concetto che qualsiasi array sia effettivamente un puntatore.Ma non è strettamente vero. Un array è una variabile che contiene un insieme contiguo di dimensioni fisse di elementi dello stesso tipo. Quindi quando dichiari un array come int x[2]
stai dichiarando una variabile che contiene due interi. Si noti che non contiene alcun puntatore.
Ora la radice di questo comune equivoco è che in C/C++ un nome di matrice valuta all'indirizzo del suo primo elemento e pertanto può essere utilizzato come puntatore. In altre parole, quando si scrive x
, si intende implicitamente &x
o &x[0]
. Questo probabilmente è stato fatto per rendere le espressioni più leggibili.
Un array multidimensionale è semplicemente una matrice di matrici. In altre parole, la stessa logica si applica a loro, non c'è nulla di speciale. Leggi la dichiarazione C/C++ a partire dal nome e vai fuori, applicando i modificatori mentre li incontri, prima [] e(), poi *, quindi scrivi, quindi interpreti una matrice multidimensionale come questa (ordine di lettura specificato esplicitamente):
int x [ 2] [ 5];
6. "of type int" 1. "x" 2. "is an array" 3. "of 2". 4. "arrays" 5. "of 5 elements"
Quindi non v'è alcuna cosa come array multidimensionali in C/C++, ma c'è cosa come array monodimensionale di matrici unidimensionali. Come da regole per gli array monodimensionali, x
, &x
e &x[0]
tutti valutano l'indirizzo del primo elemento. Ma poiché il primo elemento è un array, x[0]
valuta l'indirizzo di quell'array, cioè l'indirizzo del suo primo elemento che è un int. Lo stesso vale per &x[0]
e &x[0][0]
. Ecco perché il valore di x[0]
è lo stesso del suo indirizzo - perché x[0]
è un array.
Si noti che mentre queste cose valutano lo stesso indirizzo, hanno tipi diversi. x
è un puntatore a un array di 5 pollici, nonché a &x[0]
, in quanto entrambi valutano l'indirizzo del primo elemento di x. x[0]
valuta l'indirizzo del primo elemento di x[0]
, quindi è un puntatore a int, lo stesso vale per &x[0][0]
. Questo esempio compila bene e stampa lo stesso indirizzo per tutti e 4 i puntatori:
int x[2][5];
int (*y1)[5] = x;
int *y2 = x[0];
int (*y3)[5] = &x[0];
int *y4 = &x[0][0];
printf("%p %p %p %p\n", y1, y2, y3, y4);
Ora, ci sono diversi layout di memoria per le matrici utilizzate in diverse lingue. Ad esempio, per un array bidimensionale è possibile raggruppare gli elementi per righe o colonne. In C/C++, poiché non ci sono matrici "vere" multidimensionali, il layout della memoria è definito implicitamente dalle regole sopra. Dal int x[2][5]
, che può essere considerato come un array bidimensionale con 2 righe e 5 colonne, in realtà è un array di 2 array, ognuno dei quali rappresenta una riga, si ottiene il layout "gruppo per righe", che viene presentato in la risposta di shybovycha.
Si noti che è anche possibile creare un array di puntatori e utilizzarlo come array multidimensionale. Le differenze rispetto agli array "consueti" multi-dimensionali sono:
- Una serie di puntatori contiene effettivamente puntatori all'interno. Cioè, indirizzi dei primi elementi dei sotto-array.
- Il layout di memoria non è contiguo. Ogni sub-array può essere assegnato ovunque, ad esempio usando malloc() o new [].
- I sotto-array possono essere di dimensioni diverse.
Il vantaggio di questo approccio è che è possibile utilizzare questo array come un puntatore a puntatore (per esempio, int **y
), che rende tutte le matrici multidimensionali di questo tipo compatibili tra loro, anche se hanno differenti dimensioni.Ma le dimensioni devono essere memorizzate separatamente in questo caso.
Si prega di leggere http://c-faq.com/aryptr/index.html –
Si consiglia di leggere la [FAQ] (http://stackoverflow.com/questions/4810664/) sull'utilizzo di matrici in C++;) – fredoverflow