Prerequisit: Introducció de punters
Considereu el programa següent:
C
#include> int> main()> {> >int> arr[5] = { 1, 2, 3, 4, 5 };> >int> *ptr = arr;> >printf>(>'%p
'>, ptr);> >return> 0;> }> |
>
>
En el programa anterior, tenim un punter ptr que apunta al 0thelement de la matriu. De la mateixa manera, també podem declarar un punter que pot apuntar a tota la matriu en lloc d'un sol element de la matriu. Aquest punter és útil quan es parla de matrius multidimensionals.
Sintaxi:
data_type (* var_name ) [size_of_array];>
Aquí:
- data_type és el tipus de dades que conté la matriu. nom_var és el nom de la variable punter. size_of_array és la mida de la matriu a la qual apuntarà el punter.
Exemple
int (*ptr)[10];>
Aquí ptr és un punter que pot apuntar a una matriu de 10 nombres enters. Com que els subíndexs tenen una prioritat més alta que la indirecta, cal incloure l'operador d'indirecció i el nom del punter entre parèntesis. Aquí el tipus de ptr és 'punter a una matriu de 10 nombres enters'.
Nota: el punter que apunta al 0thelement de matriu i el punter que apunta a tota la matriu són totalment diferents. El programa següent ho 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;> }> |
>
>Sortida
p = 0x7fff6463e890, ptr = 0x7fff6463e890 p = 0x7fff6463e894, ptr = 0x7fff6463e8a4>
Aquí, pàg és el punter a 0thelement de la matriu arr , mentre ptr és un punter que apunta a tota la matriu arr .
- El tipus base de pàg és int mentre que el tipus base de ptr és 'una matriu de 5 nombres enters'.
- Sabem que l'aritmètica del punter es realitza en relació amb la mida base, de manera que si escrivim ptr++, aleshores el punter ptr es desplaçarà cap endavant 20 bytes.
La figura següent mostra el punter p i ptr. La fletxa més fosca indica un punter a una matriu.
En desreferenciar una expressió de punter, obtenim un valor al qual apunta aquesta expressió de punter. El punter a una matriu apunta a una matriu, de manera que en desreferenciar-la, hauríem d'obtenir la matriu i el nom de la matriu denota l'adreça base. Així, cada vegada que un punter a una matriu és desreferenciat, obtenim l'adreça base de la matriu a la qual apunta.
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;> }> |
>
>Sortida
p = 0x7fff55adbff0, ptr = 0x7fff55adbff0 *p = 3, *ptr = 0x7fff55adbff0 sizeof(p) = 8, sizeof(*p) = 4 sizeof(ptr) = 8, sizeof(*ptr) = 20>
Punter a matrius multidimensionals
1. Punters i matrius bidimensionals
En una matriu bidimensional, podem accedir a cada element mitjançant dos subíndexs, on el primer subíndex representa el número de fila i el segon subíndex representa el número de columna. També es pot accedir als elements de la matriu 2D amb l'ajuda de la notació de punter. Suposem que arr és una matriu 2-D, podem accedir a qualsevol element arr[i][j] de la matriu utilitzant l'expressió de punter *(*(arr + i) + j) . Ara veurem com es pot derivar aquesta expressió.
Prenem una matriu bidimensional arr[3][4] :
int arr[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} };>
Com que la memòria d'un ordinador està organitzada de manera lineal, no és possible emmagatzemar la matriu 2-D en files i columnes. El concepte de files i columnes és només teòric, de fet, una matriu 2-D s'emmagatzema en l'ordre principal de les files, és a dir, les files es col·loquen una al costat de l'altra. La figura següent mostra com s'emmagatzemarà la matriu 2-D anterior a la memòria.
Cada fila es pot considerar com una matriu 1-D, de manera que una matriu bidimensional es pot considerar com una col·lecció de matrius unidimensionals que es col·loquen una darrere l'altra. En altres paraules, podem dir que les matrius dimensionals 2-D que es col·loquen una darrere l'altra. Així que aquí arr és una matriu de 3 elements on cada element és una matriu 1-D de 4 nombres enters.
Sabem que el nom d'una matriu és un punter constant que apunta a 0thMatriu 1-D i conté l'adreça 5000. Des de arr és un 'punter a una matriu de 4 nombres enters', segons l'aritmètica del punter, l'expressió arr + 1 representarà l'adreça 5016 i l'expressió arr + 2 representarà l'adreça 5032.
Així ho podem dir arr apunta al 0thmatriu 1-D, arr + 1 apunta a l'1stmatriu 1-D i arr + 2 apunta al 2ndMatriu 1-D.
En general podem escriure:
arr + i Points to ith element of arr ->Apunta a la matriu 1-D>>>
- Com que arr + i apunta a ithelement de arr , en desreferenciar-lo obtindrà ithelement de arr que és, per descomptat, una matriu 1-D. Així l'expressió *(arr + i) ens dóna l'adreça base de ithMatriu 1-D.
- Ho sabem, l'expressió del punter *(arr + i) és equivalent a l'expressió de subíndex arr[i] . Tan *(arr + i) que és el mateix que arr[i] ens dóna l'adreça base de ithMatriu 1-D.
- Per accedir a un element individual de la nostra matriu 2-D, hauríem de poder accedir a qualsevol jthelement de ithMatriu 1-D.
- Atès que el tipus base de *(arr + i) és int i conté l'adreça 0thelement de ithMatriu 1-D, podem obtenir les adreces dels elements posteriors al fitxer ithMatriu 1-D afegint valors enters a *(arr + i) .
- Per exemple *(arr + i) + 1 representarà l'adreça de 1stelement de 1stelement de ithmatriu 1-D i *(arr+i)+2 representarà l'adreça de 2ndelement de ithMatriu 1-D.
- De la mateixa manera *(arr + i) + j representarà l'adreça de jthelement de ithMatriu 1-D. En desreferenciar aquesta expressió podem obtenir la jthelement de la ithMatriu 1-D.
Punters i matrius tridimensionals
Així l'expressió del punter *(*(*(arr + i ) + j ) + k) és equivalent a l'expressió de subíndex arr[i][j][k].
Sabem que l'expressió *(arr + i) és equivalent a arr[i] i l'expressió *(*(arr + i) + j) és equivalent a arr[i][j]. Així que podem dir que arr[i] representa l'adreça base de ithMatriu 2-D i arr[i][j] representa l'adreça base de la jthMatriu 1-D.
Exemple
desactivar el mode de desenvolupador d'Android
L'exemple següent mostra el programa per imprimir elements de matriu 3D mitjançant punters.
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;> }> |
>
>Sortida
5 10 6 11 7 12 20 30 21 31 22 32>
La figura següent mostra com s'emmagatzema a la memòria la matriu 3D utilitzada al programa anterior.
Subscripting punter a una matriu
Suposem arr és una matriu 2-D amb 3 files i 4 columnes i ptr és un punter a una matriu de 4 nombres enters, i ptr conté l'adreça base de la matriu arr .
int arr[3][4] = {{10, 11, 12, 13}, {20, 21, 22, 23}, {30, 31, 32, 33}}; int (*ptr)[4]; ptr = arr;>
Des de ptr és un punter a la matriu 2-D de la primera fila, és a dir, una matriu de 4 nombres enters, ptr + i assenyalarà ithfila. Sobre la desreferenciació ptr + i , obtenim l'adreça base de ithfila. Per accedir a l'adreça de jthelement de ithfila podem afegir j a l'expressió del punter *(ptr + i) . Per tant, l'expressió del punter *(ptr + i) + j dóna l'adreça de jthelement de ithfila i l'expressió del punter *(*(ptr + i)+j) dóna el valor de la jthelement de ithfila.
Sabem que l'expressió de punter *(*(ptr + i) + j) és equivalent a l'expressió de subíndex ptr[i][j]. Així, si tenim una variable de punter que conté l'adreça base de la matriu 2-D, podem accedir als elements de la matriu fent doble subíndex d'aquesta variable de punter.
Exemple
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;> }> |
>
>Sortida
0x7ffc9556b790 0x7ffc9556b7a0 0x7ffc9556b7b0 0x7ffc9556b790 0x7ffc9556b7a0 0x7ffc9556b7b0 10 22 33 10 22 33>