/ / Wielowymiarowe tablice i wskaźniki w C ++ - c ++, tablice, wskaźniki, tablica wielowymiarowa

Wielowymiarowe tablice i wskaźniki w C ++ - c ++, tablice, wskaźniki, tablica wielowymiarowa

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.

  1. a jest adresem pierwszego elementu, prawda? W jednowymiarowych tablicach, *a powinna być wartością pierwszego elementu, ale zamiast tego jest taka sama jak a?! Co robi *a nawet znaczy w tym kontekście?

  2. Dlaczego jest a + 1 różny od *a + 1?

Odpowiedzi:

2 dla odpowiedzi № 1

Dwuwymiarowa 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