logo

Puntatore a un array | Puntatore di matrice

Prerequisito: Introduzione ai puntatori

Consideriamo il seguente programma:



C






#include> int> main()> {> >int> arr[5] = { 1, 2, 3, 4, 5 };> >int> *ptr = arr;> >printf>(>'%p '>, ptr);> >return> 0;> }>



>

>

Nel programma sopra, abbiamo un puntatore ptr che punta allo 0thelemento dell'array. Allo stesso modo, possiamo anche dichiarare un puntatore che possa puntare all'intero array invece che a un solo elemento dell'array. Questo puntatore è utile quando si parla di array multidimensionali.

Sintassi:

data_type  (* var_name ) [size_of_array];>

Qui:

    data_type è il tipo di dati contenuti nell'array. var_name è il nome della variabile puntatore. size_of_array è la dimensione dell'array a cui punterà il puntatore.

Esempio

int (*ptr)[10];>

Qui ptr è un puntatore che può puntare a un array di 10 numeri interi. Poiché il pedice ha una precedenza maggiore rispetto all'indiretto, è necessario racchiudere l'operatore dell'indiretto e il nome del puntatore tra parentesi. Qui il tipo di ptr è 'puntatore a un array di 10 numeri interi'.

Nota: il puntatore che punta allo 0thL'elemento dell'array e il puntatore che punta all'intero array sono totalmente diversi. Il seguente programma lo mostra:

C




// C program to understand difference between> // pointer to an integer and pointer to an> // array of integers.> #include> int> main()> {> >// Pointer to an integer> >int> *p;> > >// Pointer to an array of 5 integers> >int> (*ptr)[5];> >int> arr[5];> > >// Points to 0th element of the arr.> >p = arr;> > >// Points to the whole array arr.> >ptr = &arr;> > >printf>(>'p = %p, ptr = %p '>, p, ptr);> > >p++;> >ptr++;> > >printf>(>'p = %p, ptr = %p '>, p, ptr);> > >return> 0;> }>

>

>

Produzione

p = 0x7fff6463e890, ptr = 0x7fff6463e890 p = 0x7fff6463e894, ptr = 0x7fff6463e8a4>

Qui, P è puntatore a 0thelemento dell'array arr , Mentre ptr è un puntatore che punta all'intero array arr .

  • Il tipo base di P è int mentre il tipo base di ptr è 'un array di 5 numeri interi'.
  • Sappiamo che l'aritmetica del puntatore viene eseguita rispetto alla dimensione della base, quindi se scriviamo ptr++, allora il puntatore ptr verrà spostato in avanti di 20 byte.

La figura seguente mostra i puntatori p e ptr. La freccia più scura indica un puntatore a un array.

Dereferenziando un'espressione del puntatore otteniamo un valore puntato da quell'espressione del puntatore. Il puntatore a un array punta a un array, quindi dereferenziandolo dovremmo ottenere l'array e il nome dell'array denota l'indirizzo di base. Quindi ogni volta che un puntatore a un array viene dereferenziato, otteniamo l'indirizzo base dell'array a cui punta.

C




// C program to illustrate sizes of> // pointer of array> #include> int> main()> {> >int> arr[] = { 3, 5, 6, 7, 9 };> >int> *p = arr;> >int> (*ptr)[5] = &arr;> > >printf>(>'p = %p, ptr = %p '>, p, ptr);> >printf>(>'*p = %d, *ptr = %p '>, *p, *ptr);> > >printf>(>'sizeof(p) = %lu, sizeof(*p) = %lu '>,> >sizeof>(p),>sizeof>(*p));> >printf>(>'sizeof(ptr) = %lu, sizeof(*ptr) = %lu '>,> >sizeof>(ptr),>sizeof>(*ptr));> >return> 0;> }>

>

>

Produzione

p = 0x7fff55adbff0, ptr = 0x7fff55adbff0 *p = 3, *ptr = 0x7fff55adbff0 sizeof(p) = 8, sizeof(*p) = 4 sizeof(ptr) = 8, sizeof(*ptr) = 20>

Puntatore a array multidimensionali

1. Puntatori e array bidimensionali

In un array bidimensionale, possiamo accedere a ciascun elemento utilizzando due pedici, dove il primo pedice rappresenta il numero di riga e il secondo pedice rappresenta il numero di colonna. È possibile accedere agli elementi dell'array 2D anche con l'aiuto della notazione del puntatore. Supponiamo che arr sia un array 2D, possiamo accedere a qualsiasi elemento arr[i][j] dell'array utilizzando l'espressione puntatore *(*(arr + i) + j) . Ora vedremo come si può derivare questa espressione.
Prendiamo un array bidimensionale arr[3] [4] :

int arr[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} };>

Poiché la memoria di un computer è organizzata linearmente, non è possibile memorizzare l'array 2D in righe e colonne. Il concetto di righe e colonne è solo teorico, in realtà un array 2D viene memorizzato in ordine di riga principale, ovvero le righe sono posizionate una accanto all'altra. La figura seguente mostra come verrà archiviato in memoria l'array 2D di cui sopra.

Ogni riga può essere considerata come un array unidimensionale, quindi un array bidimensionale può essere considerato come una raccolta di array unidimensionali posizionati uno dopo l'altro. In altre parole, possiamo dire che si tratta di array bidimensionali posizionati uno dopo l'altro. Ecco arr è un array di 3 elementi in cui ciascun elemento è un array 1-D di 4 numeri interi.
Sappiamo che il nome di un array è un puntatore costante che punta a 0thArray 1-D e contiene l'indirizzo 5000. Dal arr è un 'puntatore a un array di 4 numeri interi', secondo l'aritmetica dei puntatori l'espressione arr + 1 rappresenterà l'indirizzo 5016 e l'espressione arr + 2 rappresenterà l'indirizzo 5032.
Quindi possiamo dirlo arr punta allo 0thmatrice 1D, arr + 1 indica 1stArray 1-D e arr + 2 punta al 2ndmatrice 1D.

In generale possiamo scrivere:

 arr + i Points to ith element of arr ->Punta all'i-esimo array 1-D>
  • Poiché arr + i punta a ithelemento di arr , al dereferenziamento otterrà ithelemento di arr che è ovviamente un array 1-D. Così l'espressione *(arr + i) ci dà l'indirizzo base di ithmatrice 1D.
  • Conosciamo l'espressione del puntatore *(arr + i) è equivalente all'espressione in pedice arr[i] . COSÌ *(arr + i) che è lo stesso di arr[i] ci dà l'indirizzo base di ithmatrice 1D.
  • Per accedere a un singolo elemento del nostro array 2D, dovremmo essere in grado di accedere a qualsiasi jthelemento di ithmatrice 1D.
  • Poiché il tipo base di *(arr + i) È int e contiene l'indirizzo 0thelemento di ithArray 1-D, possiamo ottenere gli indirizzi degli elementi successivi nell'ithArray 1-D aggiungendo valori interi a *(arr + i) .
  • Per esempio *(arr + i) + 1 rappresenterà l'indirizzo di 1stelemento di 1stelemento di ithArray 1-D e *(arr+i)+2 rappresenterà l'indirizzo di 2ndelemento di ithmatrice 1D.
  • Allo stesso modo *(arr + i) + j rappresenterà l'indirizzo di jthelemento di ithmatrice 1D. Dereferenziando questa espressione si ottiene la jthelemento dell'ithmatrice 1D.

Puntatori e array tridimensionali

int arr[2][3][2] = { {{5, 10}, {6, 11}, {7, 12}}, {{20, 30}, {21, 31}, {22, 32}} };>

In un array tridimensionale possiamo accedere a ciascun elemento utilizzando tre pedici. Prendiamo un array 3D: possiamo considerare un array tridimensionale come un array di un array 2D, ovvero ogni elemento di un array 3D è considerato un array 2D. La matrice 3D arr può essere considerato come un array composto da due elementi in cui ciascun elemento è un array 2D. Il nome della matrice arr è un puntatore allo 0thmatrice 2D.

Quindi l'espressione del puntatore *(*(*(arr + i ) + j ) + k) è equivalente all'espressione in pedice arr[i][j][k].
Sappiamo che l'espressione *(arr + i) è equivalente a arr[i] e l'espressione *(*(arr + i) + j) è equivalente a arr[i][j]. Quindi possiamo dire che arr[i] rappresenta l'indirizzo base di ithArray 2-D e arr[i][j] rappresenta l'indirizzo di base di jthmatrice 1D.

Esempio

df.loc

L'esempio seguente mostra il programma per stampare elementi di una matrice 3D utilizzando i puntatori.

C




// C program to print the elements of 3-D> // array using pointer notation> #include> int> main()> {> >int> arr[2][3][2] = {> >{> >{5, 10},> >{6, 11},> >{7, 12},> >},> >{> >{20, 30},> >{21, 31},> >{22, 32},> >}> >};> >int> i, j, k;> >for> (i = 0; i <2; i++)> >{> >for> (j = 0; j <3; j++)> >{> >for> (k = 0; k <2; k++)> >printf>(>'%d '>, *(*(*(arr + i) + j) +k));> >printf>(>' '>);> >}> >}> >return> 0;> }>

>

>

Produzione

5 10 6 11 7 12 20 30 21 31 22 32>

La figura seguente mostra come viene archiviato in memoria l'array 3D utilizzato nel programma precedente.

Puntatore di sottoscrizione a un array

Supponiamo arr è un array 2D con 3 righe e 4 colonne e ptr è un puntatore a un array di 4 numeri interi e ptr contiene l'indirizzo base dell'array arr .

int arr[3][4] = {{10, 11, 12, 13}, {20, 21, 22, 23}, {30, 31, 32, 33}}; int (*ptr)[4]; ptr = arr;>

Da ptr è un puntatore all'array 2-D della prima riga, ovvero un array di 4 numeri interi, ptr+i indicherà ithriga. Sul dereferenziamento ptr+i , otteniamo l'indirizzo di base di ithriga. Per accedere all'indirizzo di jthelemento di ithriga possiamo aggiungere j all'espressione del puntatore *(ptr + i) . Quindi l'espressione del puntatore *(ptr + i) + j dà l'indirizzo di jthelemento di ithriga e l'espressione del puntatore *(*(ptr + i)+j) dà il valore di jthelemento di ithriga.
Sappiamo che l'espressione puntatore *(*(ptr + i) + j) è equivalente all'espressione pedice ptr[i][j]. Quindi, se abbiamo una variabile puntatore contenente l'indirizzo di base dell'array 2-D, allora possiamo accedere agli elementi dell'array eseguendo un doppio indice di quella variabile puntatore.

Esempio

C




// C program to print elements of a 2-D array> // by scripting a pointer to an array> #include> int> main()> {> >int> arr[3][4] = {> >{10, 11, 12, 13},> >{20, 21, 22, 23},> >{30, 31, 32, 33}> >};> >int> (*ptr)[4];> >ptr = arr;> >printf>(>'%p %p %p '>, ptr, ptr + 1, ptr + 2);> >printf>(>'%p %p %p '>, *ptr, *(ptr + 1), *(ptr + 2));> >printf>(>'%d %d %d '>, **ptr, *(*(ptr + 1) + 2), *(*(ptr + 2) + 3));> >printf>(>'%d %d %d '>, ptr[0][0], ptr[1][2], ptr[2][3]);> >return> 0;> }>

>

>

Produzione

0x7ffc9556b790 0x7ffc9556b7a0 0x7ffc9556b7b0 0x7ffc9556b790 0x7ffc9556b7a0 0x7ffc9556b7b0 10 22 33 10 22 33>