C/Wskaźniki - więcej: Różnice pomiędzy wersjami
Usunięta treść Dodana treść
Podana była tylko symulacja tablicy dwuwymiarowej + drobne poprawki. |
→Tablice wielowymiarowe: poprawki: 1) to nie C++, 2) złe zwalnianie pamięci, 3) uzupełnienie treści i tłumaczenia 4) wiele innych |
||
Linia 218:
[[Grafika:Array of array storage.svg|thumb|180px|tablica dwuwymiarowa — w rzeczywistości tablica ze wskaźnikami do tablic]]
W rozdziale [[../Tablice/]] pokazaliśmy, jak tworzyć tablice wielowymiarowe, gdy ich rozmiar jest znany w czasie kompilacji. Teraz zaprezentujemy, jak to wykonać za pomocą wskaźników i to w sytuacji, gdy rozmiar może
<source lang="C">
int
printf("Podaj rozmiar tabliczki mnozenia: ");
scanf("%d",
int **tabliczka = (int **)malloc(
for(
{
}
/* tutaj można
/* i operować na niej. Gdy już wykonamy wszystkie czynności.. */
for(i=0; i<rozmiar; ++i) /* 3 */
free(tabliczka); /* 4 */
tabliczka = NULL;
</source>
Przydzielanie pamięci wygląda następująco: najpierw dla pierwszego wymiaru tablicy, który jest zarazem "tablicą tablic" (1) - tak jak na rysunku, jest to tablica przechowywująca wskaźniki do szeregu kolejnych tablic, w których przechowywane są już liczby. W drugim kroku (2) przydzielamy pamięć wszystkim tym tablicom. Tablica jest typu int* (wskaźnik na pierwszy element tablicy), natomiast tablica tablic jest typu int** (wskaźnik na pierwszy element, którym jest wskaźnik na tablicę). Jako że malloc jako argument przyjmuje rozmiar pamięci w bajtach, posługujemy się konstrukcją sizeof element. Pobiera ona typ i zwraca jego rozmiar, w naszym przypadku - (*tabliczka) oznacza to samo, co tabliczka[0], więc jest pierwszą podtablicą i ma typ int*. Jest to typ wskaźnikowy, dlatego sizeof zwróci ilość bajtów jakie wymaga wskaźnik. Drugim razem używamy jako argumentu (**tabliczka), co odpowiada użyciu tabliczka[0][0] (pierwsza liczba w pierwszej tablicy), które to ma już typ int - sizeof zwróci ilość bajtów odpowiadających zmiennej liczbowej. Dla systemu x86 dla obu sizeof powinniśmy otrzymać wielkość 4 bajty, jednak może to się zmienić dla różnych kompilatorów, a tym bardziej dla systemu x64.<br />
Tablicę zwalniamy najpierw zwalniając wszystkie podtablice (3), a potem tablicę główną (4). Należy nie pomylić kolejności - gdybyśmy najpierw zwolnili pamięć tablicy trzymającej wskaźniki na tablice, wówczas próba uzyskania dalszych tablic mogłaby się zakończyłaby błędem aplikacji (odczyt ze zwolnionej pamięci).
Możemy również symulować tablicę dwuwymiarową za pomocą tablicy jednowymiarowej:
<source lang="c">
int *tabliczka = (int *)malloc(
</source>
W tym przypadku alokujemy pamięć równą liczbie elementów tablicy dwuwymiarowej, jednak w tablicy jednowymiarowej. Na przykład, dla rozmiaru równego 5 zaalokujemy tablicę jednowymiarową z 25 elementami. W ten sposób wszystkie elementy tablicy znajdą się w pamięci obok siebie, jednak utrudnia to programiście dostęp do nich, a także operacje na nich (potrzebna jest do tego [[#Arytmetyka wskaźników|Arytmetyka wskaźników]]).
Zauważmy, że
0123
012
Linia 260 ⟶ 257:
<source lang="C">
const size_t wymiary[] = { 2, 4, 6, 8, 1, 3, 5, 7, 9 };
const size_t ilosc_podtablic = sizeof (wymiary) / sizeof (*wymiary);
int i;
int **tablica = malloc(
for (i = 0; i<
tablica[i] = malloc(wymiary[i] * sizeof **tablica);
}
</source>
Gdy nabierzesz wprawy w używaniu wskaźników oraz innych funkcji malloc i realloc, nauczysz się wykonywać różne inne operacje, takie jak dodawanie kolejnych wierszy, usuwanie wierszy, zmiana rozmiaru wierszy, zamiana wierszy miejscami itp.
== Wskaźniki na funkcje ==
|