Wskaźnik do tablicy | Wskaźnik tablicy
Warunek wstępny: Wprowadzenie do wskaźników
Rozważmy następujący program:
C
#include> int> main()> {> > int> arr[5] = { 1, 2, 3, 4, 5 };> > int> *ptr = arr;> > printf> (> '%p
'> , ptr);> > return> 0;> }> |
W powyższym programie mamy wskaźnik pt co wskazuje na 0 t element tablicy. Podobnie możemy również zadeklarować wskaźnik, który może wskazywać na całą tablicę, a nie tylko na jeden element tablicy. Ten wskaźnik jest przydatny, gdy mówimy o tablicach wielowymiarowych.
Składnia:
data_type (* var_name ) [size_of_array];
Tutaj:
- typ_danych to typ danych przechowywanych w tablicy. nazwa_zmiennej to nazwa zmiennej wskaźnikowej. size_of_array to rozmiar tablicy, na którą będzie wskazywał wskaźnik.
Przykład
int (*ptr)[10];
Tutaj pt jest wskaźnikiem, który może wskazywać tablicę składającą się z 10 liczb całkowitych. Ponieważ indeks dolny ma wyższy priorytet niż pośredni, konieczne jest ujęcie operatora pośredniego i nazwy wskaźnika w nawiasach. Tutaj typem ptr jest „wskaźnik do tablicy zawierającej 10 liczb całkowitych”.
Uwaga: Wskaźnik wskazujący na 0 t element tablicy i wskaźnik wskazujący na całą tablicę są zupełnie inne. Poniższy program to pokazuje:
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;> }> |
Wyjście
p = 0x7fff6463e890, ptr = 0x7fff6463e890 p = 0x7fff6463e894, ptr = 0x7fff6463e8a4
Tutaj, P jest wskaźnikiem na 0 t element tablicy przyr , chwila pt jest wskaźnikiem wskazującym na całą tablicę przyr .
- Podstawowy typ P jest int podczas gdy typ bazowy pt to „tablica 5 liczb całkowitych”.
- Wiemy, że arytmetyka wskaźnika wykonywana jest względem rozmiaru bazowego, więc jeśli napiszemy ptr++, to wskaźnik pt zostanie przesunięty do przodu o 20 bajtów.
Poniższy rysunek przedstawia wskaźnik p i ptr. Ciemniejsza strzałka oznacza wskaźnik do tablicy.
Po wyłuskaniu wyrażenia wskaźnikowego otrzymujemy wartość wskazywaną przez to wyrażenie wskaźnikowe. Wskaźnik do tablicy wskazuje na tablicę, zatem dereferując ją powinniśmy otrzymać tablicę, a nazwa tablicy oznacza adres bazowy. Zatem za każdym razem, gdy następuje dereferencja wskaźnika do tablicy, otrzymujemy adres podstawowy tablicy, na którą wskazuje.
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;> }> |
Wyjście
p = 0x7fff55adbff0, ptr = 0x7fff55adbff0 *p = 3, *ptr = 0x7fff55adbff0 sizeof(p) = 8, sizeof(*p) = 4 sizeof(ptr) = 8, sizeof(*ptr) = 20
Wskaźnik do tablic wielowymiarowych
1. Wskaźniki i tablice dwuwymiarowe
W tablicy dwuwymiarowej dostęp do każdego elementu można uzyskać za pomocą dwóch indeksów dolnych, gdzie pierwszy indeks dolny reprezentuje numer wiersza, a drugi indeks dolny oznacza numer kolumny. Dostęp do elementów tablicy 2-D można uzyskać również za pomocą notacji wskaźnikowej. Załóżmy, że arr jest tablicą 2-D, możemy uzyskać dostęp do dowolnego elementu arr[i] tablicy za pomocą wyrażenia wskaźnikowego *(*(arr + i) + j) . Zobaczymy teraz, jak można wyprowadzić to wyrażenie.
Weźmy tablicę dwuwymiarową arr[3] [4] :
int arr[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} };
Ponieważ pamięć komputera jest zorganizowana liniowo, nie jest możliwe przechowywanie tablicy 2-D w wierszach i kolumnach. Koncepcja wierszy i kolumn jest jedynie teoretyczna, w rzeczywistości tablica 2-D jest przechowywana w kolejności głównych wierszy, tj. wiersze są umieszczane obok siebie. Poniższy rysunek pokazuje, jak powyższa tablica 2-D będzie przechowywana w pamięci.
Każdy wiersz można uznać za tablicę 1-D, zatem tablicę dwuwymiarową można uznać za zbiór tablic jednowymiarowych umieszczonych jedna po drugiej. Innymi słowy, możemy powiedzieć, że tablice wymiarowe 2-D są umieszczane jedna po drugiej. Więc tu przyr jest tablicą składającą się z 3 elementów, gdzie każdy element jest tablicą 1-D złożoną z 4 liczb całkowitych.
Wiemy, że nazwą tablicy jest stały wskaźnik wskazujący na 0 t Tablica 1-D i zawiera adres 5000. Od przyr jest „wskaźnikiem do tablicy składającej się z 4 liczb całkowitych”, zgodnie z arytmetyką wskaźników wyrażenie arr + 1 będzie reprezentować adres 5016, a wyrażenie arr + 2 będzie reprezentować adres 5032.
Więc możemy tak powiedzieć przyr wskazuje na 0 t tablica 1-D, tablica + 1 wskazuje na 1 ul Tablica 1-D i ar + 2 wskazuje na 2 II Tablica 1-D.
Ogólnie możemy napisać:
arr + i Points to ith element of arr ->Wskazuje i-tą tablicę 1-D
- Ponieważ arr + i wskazuje na i t element przyr , po wyłuskaniu otrzyma i t element przyr co jest oczywiście tablicą 1-D. Stąd wyrażenie *(arr + i) daje nam adres bazowy i t Tablica 1-D.
- Wiemy, wyrażenie wskaźnikowe *(arr + i) jest równoważne wyrażeniu z indeksem dolnym Arr[i] . Więc *(arr + i) co jest takie samo jak Arr[i] daje nam adres bazowy i t Tablica 1-D.
- Aby uzyskać dostęp do pojedynczego elementu naszej tablicy 2-D, powinniśmy mieć dostęp do dowolnego elementu j t element I t Tablica 1-D.
- Ponieważ podstawowy typ *(arr + i) Jest wew i zawiera adres 0 t element I t tablicy 1-D, możemy uzyskać adresy kolejnych elementów w i t Tablica 1-D poprzez dodanie wartości całkowitych *(arr + i) .
- Na przykład *(arr + i) + 1 będzie reprezentować adres 1 ul element 1 ul element I t Tablica 1-D i *(arr+i)+2 będzie reprezentować adres 2 II element I t Tablica 1-D.
- Podobnie *(arr + i) + j będzie reprezentować adres j t element I t Tablica 1-D. Po wyłuskaniu tego wyrażenia możemy otrzymać j t element I t Tablica 1-D.
Wskaźniki i tablice trójwymiarowe
int arr[2][3][2] = { {{5, 10}, {6, 11}, {7, 12}}, {{20, 30}, {21, 31}, {22, 32}} }; W tablicy trójwymiarowej dostęp do każdego elementu można uzyskać za pomocą trzech indeksów dolnych. Weźmy tablicę 3-D. Tablicę trójwymiarową możemy uznać za tablicę tablicy 2-D, tj. każdy element tablicy 3-D jest uważany za tablicę 2-D. Tablica 3-D przyr można uznać za tablicę składającą się z dwóch elementów, gdzie każdy element jest tablicą 2-D. Nazwa tablicy przyr jest wskaźnikiem do 0 t Tablica 2-D.
Stąd wyrażenie wskaźnikowe *(*(*(arr + i ) + j ) + k) jest równoważne wyrażeniu w indeksie dolnym arr[i][j][k].
Wiemy, że wyrażenie *(arr + i) jest równoważne arr[i], a wyrażenie *(*(arr + i) + j) jest równoważne arr[i][j]. Możemy więc powiedzieć, że arr[i] reprezentuje adres bazowy i t Tablica 2-D, a arr[i][j] reprezentuje adres podstawowy j t Tablica 1-D.
Przykład
Poniższy przykład demonstruje program do drukowania elementów tablicy 3D za pomocą wskaźników.
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;> }> |
Wyjście
5 10 6 11 7 12 20 30 21 31 22 32
Poniższy rysunek pokazuje, w jaki sposób tablica 3-D używana w powyższym programie jest przechowywana w pamięci.
Wskaźnik subskrypcyjny do tablicy
Przypuszczać przyr jest tablicą 2-D z 3 wierszami i 4 kolumnami oraz pt jest wskaźnikiem do tablicy składającej się z 4 liczb całkowitych, oraz pt zawiera adres podstawowy tablicy przyr .
int arr[3][4] = {{10, 11, 12, 13}, {20, 21, 22, 23}, {30, 31, 32, 33}}; int (*ptr)[4]; ptr = arr;
Od pt jest wskaźnikiem do pierwszego wiersza tablicy 2-D, tj. tablicy 4 liczb całkowitych, pt + i wskaże i t wiersz. O dereferencji pt + i , otrzymujemy adres bazowy i t wiersz. Aby uzyskać dostęp do adresu j t element I t wierszu możemy dodać j do wyrażenia wskaźnikowego *(ptr + i) . Zatem wyrażenie wskaźnikowe *(ptr + i) + j podaje adres j t element I t wiersz i wyrażenie wskaźnikowe *(*(ptr + i)+j) podaje wartość j t element I t wiersz.
Wiemy, że wyrażenie wskaźnikowe *(*(ptr + i) + j) jest równoważne wyrażeniu indeksu dolnego ptr[i][j]. Jeśli więc mamy zmienną wskaźnikową zawierającą adres bazowy tablicy 2-D, wówczas możemy uzyskać dostęp do elementów tablicy poprzez podwójne indeksowanie tej zmiennej wskaźnikowej.
Przykład
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;> }> |
Wyjście
0x7ffc9556b790 0x7ffc9556b7a0 0x7ffc9556b7b0 0x7ffc9556b790 0x7ffc9556b7a0 0x7ffc9556b7b0 10 22 33 10 22 33