W języku C wskaźnik do typu T
wskazuje lokalizację, w której są przechowywane niektóre dane typu T
. Aby wszystko było konkretne, omówię poniżej: T = int
.
Najprostsze wykorzystanie wskaźnika może być wskazanie do jednej wartości:
int a = 42;
int *pa = &a;
Teraz *pa
i a
są zarówno takie same i równe 42
. Również *pa
i pa[0]
oba równoważne: tak, na przykład, można zrobić:
*pa += 1; /* a is 43 */
pa[0] += 1; /* a is 44 */
a += 1; /* a is 45 */
W rzeczywistości, kompilator C przekłada pa[0]
do *(pa+0)
automatycznie.
Wskaźnik może wskazywać na miejscu, które znajduje się wewnątrz sekwencji danych:
int arr[] = { 1, 2, 3 }; /* 3 ints */
int *parr = arr; /* points to 1 */
Teraz nasza pamięć wygląda następująco:
+---+---+---+
arr: | 1 | 2 | 3 |
+---+---+---+
+------+ |
| parr | ----+
+------+
parr
to wskaźnik, który wskazuje na pierwszy element arr
na powyższym rysunku. Nawiasem mówiąc, parr
ma również pudełko dookoła, ponieważ musimy przechowywać obiekt gdzieś w pamięci obiektu parr
. Wartość parr
jest adresem pierwszego elementu z arr
.
Teraz możemy użyć parr
aby uzyskać dostęp do elementów arr
:
arr[0] == parr[0]; /* true */
parr[1]++; /* make arr[1] equal to 3 */
Tak, wskaźnik może być używany w znaczeniu „Zwracam się do pierwszego z n elementów w ciągłym sklepie niektórych obiektów” . Oczywiście trzeba wiedzieć, ile obiektów istnieje, aby ten schemat działał: ale gdy już to pamiętamy, jest to bardzo wygodny sposób dostępu do pamięci w C.
Wskaźnik może wskazywać dynamicznie przydzielona pamięć, a także:
#include <stdlib.h>
size_t n;
/* now, obtain a value in n at runtime */
int *p = malloc(n * sizeof *p);
Jeśli połączenie malloc()
powiedzie powyżej p
wskazuje teraz do pierwszego z przyległej strefy przeznaczonej dla 10 int
s. Możemy teraz używać w naszym programie od p[0]
do p[n-1]
.
Prawdopodobnie znasz większość lub wszystkie z powyższych :-), ale mimo to powyższe pomaga zrozumieć, co powiem dalej.
Pamiętaj, że powiedzieliśmy, że wskaźnik może wskazywać na ciągłą sekwencję obiektów tego samego typu? "Ten sam typ" może być również innym typem wskaźnika.
#include <stdlib.h>
int **pp;
pp = malloc(3 * sizeof *pp);
Teraz pp
punkty do int *
. Wracając do naszych wcześniejszych zdjęciu:
+------+------+------+
| | | |
+------+------+------+
+------+ |
| pp | ----+
+------+
a każdy z 3 pól jest int *
, które mogą wskazywać na pierwszy element ciągłej sekwencji int
S:
for (i=0; i < 3; ++i)
pp[i] = malloc((i + 1) * sizeof *ppi[i]);
Tutaj przydzielane przestrzeń dla jednej int w pp[0]
, 2 w pp[1]
i 3 w pp[3]
:
+------+ +---+
pp -------->| |-------->| |
+------+ +---+---+
| |-------->| | |
+------+ +---+---+---+
| |-------->| | | |
+------+ +---+---+---+
Więc pp[0]
jest wskaźnikiem do jednego int
, a int
jest jedynym int
w dynamicznie przydzielonym bloku int
s. Innymi słowy, pp[0][0]
jest int
i wskazuje na najwyższe pole powyżej "width-3" powyżej. Podobnie, oba znaki są poprawne i są dwoma polami pod polem pp[0][0]
.
Najczęstsze zastosowanie wskaźnika do wskaźnika jest stworzenie 2-wymiarową tablicę „” w czasie wykonywania:
int **data;
size_t i;
data = malloc(n * sizeof *data);
for (i=0; i < n; ++i)
data[i] = malloc(m * sizeof *data[i]);
Teraz, przy założeniu, że wszystkie malloc()
s uda, data[0]
... data[n-1]
są prawidłowymi wartościami int *
, z których każda wskazuje na osobną długość m
sąsiednich obiektów .
Ale, jak pokazałem powyżej, wskaźnik do wskaźnika nie musi mieć tej samej "liczby elementów" w każdym z jej "wierszy". Najbardziej oczywistym przykładem jest argv
in main()
.
Teraz, jak można się domyślić, to „głębokie” 3-poziomowy wskaźnik, takich jak int ***p;
jest w porządku i mogą być przydatne w C.
Tak Byłoby 3 tablice wymiar jest gdzie zaczyna się dostać nieco trudny, po 3 wymiarowych tablicach moja głowa zaczyna boleć i próbuję znaleźć inny sposób przechowywania moich danych. – Craig
Tablica 3 wymiarowa jest jak przechowywanie informacji w podzielonym na sekcje polu, więc jeśli masz pudełko wielkości 10x10x10, a każdy 1x1x1 przechowuje pewną informację, możesz przechowywać 1000 informacji. Ale tak jak powiedziałem po trzech wskaźnikach, możesz chcieć spojrzeć na inny sposób przechowywania danych. Przykład użycia tablicy 3D to obraz, np. Mapa bitowa wielkości 1024x1024, a przy każdym z pikseli na obrazie, który chcesz zapisać wartość R, G, B, możesz mieć tablicę o wymiarach 1024x1024x3, co oznacza pozycja na siatce 1024x1024 możesz zapisać [0] [1] i [2] liczbę danych. – Craig