Powiedzmy, że deklaruję i inicjuję następującą tablicę wielowymiarową w C ++:
unsigned a[3][4] = {
{12, 6, 3, 2},
{9, 13, 7, 0},
{7, 4, 8, 5}
};
Po czym wykonuję ten kod:
cout << a << endl; // output: 0x7fff5afc5bc0
cout << a + 1 << endl; // output: 0x7fff5f0afbd0
cout << *a << endl; // output: 0x7fff5afc5bc0
cout << *a + 1 << endl; // output: 0x7fff5f0afbc4
Po prostu nie rozumiem, co się tutaj dzieje.
a
jest adresem pierwszego elementu, prawda? W jednowymiarowych tablicach,*a
powinna być wartością pierwszego elementu, ale zamiast tego jest taka sama jaka
?! Co robi*a
nawet znaczy w tym kontekście?Dlaczego jest
a + 1
różny od*a + 1
?
Odpowiedzi:
2 dla odpowiedzi № 1Dwuwymiarowa tablica to tablica macierzy. Możesz wizualizować a
tak jak
a = { a[0], a[1], a[2]}
i a[0]
, a[1]
, a[2]
tak jak
a[0] = { a[0][0], a[0][1], a[0][2], a[0][3]};
a[1] = { a[1][0], a[1][1], a[1][2], a[1][3]};
a[1] = { a[2][0], a[2][1], a[2][2], a[2][3]};
Analiza twojego pierwszego pytania
a
jest adresem pierwszego elementu, prawda?
tak a
jest adresem pierwszego elementu i pierwszym elementem a
jest a[0]
który jest adresem pierwszego elementu a[0][0]
.
* a powinno być wartością pierwszego elementu, ale zamiast tego jest takie samo jak?
tak *a
powinna być wartością pierwszego elementu, który się odnosi a[0]
. I widzimy a[0]
jest adresem a[0][0]
tak jak a
. A zatem *a
mają taką samą wartość jak a
który jest adresem a[0][0]
.
Co * oznacza nawet w tym kontekście?
Wcześniej udzielono odpowiedzi, *a
jest adresem pierwszego elementu pierwszej tablicy a[0][0]
, i *(a+1)
jest adresem drugiego elementu pierwszej tablicy a[1][0]
.
I analiza twojego drugiego pytania
Dlaczego jest
a + 1
różny od*a + 1
?
W tej chwili być może możesz odpowiedzieć na własne pytanie.
a
jest adresem a[0]
następnie
a+1
jest adresem a[1]
które posiadają adres a[1][0]
. Możesz wydrukować wartość według
cout<<**(a+1)<<endl; // 9
Inny sposób *a
jest wartością a[0]
który jest adresem a[0][0]
. Więc *a+1
jest adresem a[0][1]
. Możesz wydrukować wartość jako
cout<<*(*a+1)<<endl; // 6
3 dla odpowiedzi № 2
Powinieneś spróbować znaleźć dobrą dokumentację na temat wskaźników, tablic i rozkładu tablicowego. W Twoim przypadku, unsigned a[3][4]
jest dwuwymiarową tablicą typów unsigned [3][4]
. Kiedykolwiek to określasz jako a
, rozpada się na wskaźnik unsigned[4]
, więc zepsuty typ a
jest unsigned (*)[4]
. Dlatego dereferencja daje ci tablicę, więc *a
jest tablicą [12, 6, 3, 2]
(technicznie jest to wskaźnik do pierwszego elementu w tablicy).
Teraz, a+1
oznacza "zwiększyć wskaźnik do unsigned[4]
o 1 ", w twoim przypadku" przeskakuje "4 unsigneds do pamięci, więc teraz a+1
wskazuje na "wiersz" indeksowany przez 1 w twoim przykładzie. Dereferencje to *(a+1)
plonuje samą tablicę ([9,13,7,0]
) (tj. wskaźnik do pierwszego elementu), a ponowne wyłuskiwanie daje ci pierwszy element, tj. **(a+1)
równa się 9
.
Z drugiej strony, *a+1
pierwsze dereferencje a
, więc dostajesz pierwszy wiersz, tj. [12,6,3,2]
(ponownie, technicznie wskaźnik do pierwszego elementu tego wiersza). Następnie zwiększasz ją o jeden, więc kończysz wskazując na element 6
. Dereferencję ponownie, *(*a+1)
, plony 6
.
Pomocne może być zdefiniowanie a
równoważnie jako
typedef unsigned T[4]; // or (C++11) using T = unsigned[4];
T a[3]; // Now it"s a bit more clear how dereferencing works