Per comprenderlo appieno , devi comprendere i seguenti concetti:
Gli array non sono puntatori!
Prima di tutto (ed è stato predicato abbastanza), gli array non sono puntatori . Invece, nella maggior parte degli usi, "decadono" all'indirizzo al loro primo elemento, che può essere assegnato a un puntatore:
int a[] = {1, 2, 3};
int *p = a; // p now points to a[0]
Presumo che funzioni in questo modo in modo che sia possibile accedere ai contenuti dell'array senza copiarli tutti. Questo è solo un comportamento dei tipi di array e non intende implicare che siano la stessa cosa.
Array multidimensionali
Gli array multidimensionali sono solo un modo per "partizionare" la memoria in un modo che il compilatore / macchina possa capire e su cui operare.
Ad esempio, int a[4][3][5]
= un array contenente 4 * 3 * 5 (60) "blocchi" di memoria di dimensioni intere.
Il vantaggio rispetto all'uso di int a[4][3][5]
vs plain int b[60]
è che ora sono "partizionati" (è più facile lavorare con i loro "blocchi", se necessario) e il programma può ora eseguire il controllo del binding.
In effetti, int a[4][3][5]
viene memorizzato esattamente come int b[60]
in memoria - L' unica differenza è che il programma ora lo gestisce come se fossero entità separate di determinate dimensioni (in particolare, quattro gruppi di tre gruppi di cinque).
Tieni presente: entrambi int a[4][3][5]
e int b[60]
sono uguali in memoria e l'unica differenza è come vengono gestiti dall'applicazione / compilatore
{
{1, 2, 3, 4, 5}
{6, 7, 8, 9, 10}
{11, 12, 13, 14, 15}
}
{
{16, 17, 18, 19, 20}
{21, 22, 23, 24, 25}
{26, 27, 28, 29, 30}
}
{
{31, 32, 33, 34, 35}
{36, 37, 38, 39, 40}
{41, 42, 43, 44, 45}
}
{
{46, 47, 48, 49, 50}
{51, 52, 53, 54, 55}
{56, 57, 58, 59, 60}
}
Da questo, puoi vedere chiaramente che ogni "partizione" è solo un array di cui il programma tiene traccia.
Sintassi
Ora, gli array sono sintatticamente diversi dai puntatori . In particolare, questo significa che il compilatore / macchina li tratterà in modo diverso. Questo può sembrare un gioco da ragazzi, ma dai un'occhiata a questo:
int a[3][3];
printf("%p %p", a, a[0]);
L'esempio precedente stampa lo stesso indirizzo di memoria due volte, in questo modo:
0x7eb5a3b4 0x7eb5a3b4
Tuttavia, solo uno può essere assegnato a un puntatore in modo così diretto :
int *p1 = a[0]; // RIGHT !
int *p2 = a; // WRONG !
Perché non può a
essere assegnato a un puntatore ma a[0]
può?
Questo, semplicemente, è una conseguenza degli array multidimensionali e spiegherò perché:
A livello di " a
", vediamo ancora di avere un'altra "dimensione" a cui guardare. A livello di " a[0]
", tuttavia, siamo già nella dimensione superiore, quindi per quanto riguarda il programma stiamo solo guardando un array normale.
Potresti chiedere:
Perché è importante se l'array è multidimensionale per quanto riguarda la creazione di un puntatore per esso?
È meglio pensare in questo modo:
Un "decadimento" da un array multidimensionale non è solo un indirizzo, ma un indirizzo con dati di partizione (AKA capisce ancora che i suoi dati sottostanti sono costituiti da altri array), che consiste di limiti impostati dall'array oltre la prima dimensione.
Questa logica di "partizione" non può esistere all'interno di un puntatore a meno che non venga specificata:
int a[4][5][95][8];
int (*p)[5][95][8];
p = a; // p = *a[0] // p = a+0
In caso contrario, il significato delle proprietà di ordinamento dell'array viene perso.
Nota anche l'uso delle parentesi intorno a *p
: int (*p)[5][95][8]
- Questo per specificare che stiamo creando un puntatore con questi limiti, non un array di puntatori con questi limiti:int *p[5][95][8]
Conclusione
Ripassiamo:
- Gli array decadono in indirizzi se non hanno altro scopo nel contesto utilizzato
- Gli array multidimensionali sono solo array di array - Quindi, l'indirizzo 'decaduto' porterà il fardello di "Ho sottodimensioni"
- I dati di dimensione non possono esistere in un puntatore a meno che non gli vengano forniti .
In breve: gli array multidimensionali decadono in indirizzi che hanno la capacità di comprenderne il contenuto.