This is an old revision of the document!
W języku C można wyróżnić dwie podstawowe metody alokacji (przydzielania) pamięci:
static
), lub po zakończeniu programuint a; char str[] = "Hello!"; float tab[5];
int* tab; tab = malloc(5 * sizeof(*tab)); free(tab);
Dynamiczna alokacja pamięci pozwala przede wszystkim na:
Funkcja malloc() (od memory allocation) rezerwuje blok wolnej pamięci o zadanym rozmiarze (w bajtach) i zwraca adres jego pierwszego bajtu. W przypadku nieznalezienia wymaganego obszaru malloc()
zwraca wskaźnik zerowy (dla przypomnienia – wskaźnik o wartości 0
).
Ponieważ rezerwowany blok może być zmienną dowolnego typu, funkcja ta zwraca uniwersalny “wskaźnik na void
”. Przypisanie takiego wskaźnika do wskaźnika dowolnego innego typu jest operacją dozwoloną przez standard języka.
Aby utworzyć tablicę typu double
o zadanym rozmiarze z użyciem funkcji malloc()
można napisać następujący kod:
int rozmiar = 10; double* tab; tab = malloc(rozmiar * sizeof(*tab));
Powyższy kod zarezerwuje obszar pamięci dla 10 wartości typu wskazywanego przez tab
(czyli double
) i przypisze adres wskaźnikowi tab
. Zauważ, że zmienna tab
została zadeklarowana jako wskaźnik do pojedynczej wartości double
, a nie do bloku 10 takich wartości. Dlaczego? Ponieważ nazwa tablicy jest zarazem adresem jej pierwszego elementu, powyższe przypisanie umożliwia korzystanie z tab
jak ze zwykłej nazwy tablicy (np. tab[0]
to wartość jej pierwszego elementu).
Funkcja free() zwalnia dynamicznie przydzieloną pamięć (i tylko taką – próba zwalniania pamięci przydzielonej statycznie to błąd). Argumentem funkcji free()
jest adres obszaru pamięci do zwolnienia.
Na przykład:
double* tab; tab = malloc(8 * sizeof(*tab)); free(tab);
System operacyjny wyznacz limit pamięci, jaki może wykorzystać dany program – jego przekroczenie powoduje “ubicie” programu. Zapominając zwolnić przydzieloną pamięć można łatwo doprowadzić do wycieku pamięci i w konsekwencji właśnie do przedwczesnego zakończenia programu…
Funkcja realloc() służy do zmiany rozmiaru zaalokowanego dynamicznie bloku pamięci. Jej pierwszym argumentem jest adres bloku pamięci, a drugim – nowy rozmiar (w bajtach).
Do zwalniania pamięci przydzielonej przez realloc()
służy również funkcja free()
.
Przykład:
double* tab; int rozmiar_1 = 10; int rozmiar_2 = 20; tab = malloc(rozmiar_1 * sizeof(*tab)); tab = realloc(tab, rozmiar_2 * sizeof(*tab)); free(tab);
Aby utworzyć dynamiczną tablicę dwuwymiarową, najpierw alokujemy pamięć dla “wierszy”, a następnie dla “kolumn”. Podczas zwalniania pamięci postępujemy na odwrót – najpierw zwalniamy pamięć przydzieloną dla “kolumn”, a potem dla “wierszy”.
Przykład:
#include <stdio.h> #include <stdlib.h> int main () { int w = 6; //liczba wierszy int k = 3; // liczba kolumn double **tab2d; int i; tab2d = malloc(w * sizeof(double*)); // alokacja pamięci "wierszy" for(i = 0; i < w; i++) { tab2d[i] = malloc(k * sizeof(double)); // alokacja pamięci "kolumn" } for(i = 0; i < w; i++) { free(tab2d[i]); // zwolnienie pamieci kolumn" } free(tab2d); //uwolnienie pamieci "wierszy" tab2d = NULL; return 0; }
W poniższych ćwiczeniach każdorazowo zadbaj o poprawne zwolnienie przydzielonej dynamicznie pamięci!
(poziom trudności: )
Napisz program który alokuje dynamicznie jednowymiarową tablicę (wybranego typu), wypełnia ją losowymi liczbami, a następnie wypisuje jej elementy na ekran.
(poziom trudności: )
Zmodyfikuj program z zadania DAL1D tak, aby po utworzeniu tablicy i zainicjalizowaniu jej elementów program powiększył jej rozmiar dwukrotnie (nowe elementy wypełniając zerami) i ponownie wypisał jej elementy na ekran.
(poziom trudności: )
Napisz program który alokuje dynamicznie tablicę przechowującą w wierszach następujące wyrazy:
Oto tablica dynamiczna.