121
Przeanalizujmy teraz po kolei, co <lzieje się w powyższym fragmencie. Najpierw deklarujemy zmienne rozmiar tablicy i wskaźnik, który będzie wskazywał ohszar w pamięci, gdzie będzie trzymana tablica. Do zmiennej rozmiar możemy w trakcie działania programu przypisać cokolwiek wczytać ją z pliku, z klawiatury, obliczyć, wylosować nie jest to istotne, rozmiar * sizeof ‘tablica oblicza potrzebna wielkość tablicy. Dla każdej zmiennej float potrzebujemy tyk1 bajtów, ik* zajmuje ten typ danych. Ponieważ może się to różnić na rozmaitych maszynach, istnieje operator sizeof. zwracający dla danego wyrażenia rozmiar jego typu w I Kij tarli.
W wielu książkach (również K&Rv2) i w Internecie stosuje się inny schemat użycia funkcji malloc a mianowicie: tablica * (float*)malloc (rozmiar • sizeof (float)). Takie użycie należy traktować jako błędne, gdyż nie sprzyja ono poprawnemu wykrywaniu błędów.
Rozważmy sytuację, gdy programista zapomni (kalać plik nagłówkowy stdlib.h, wówczas kompilator (z braku deklaracji funkcji mafloc) przyjmie, że zwraca ona typ int zatem do zmiennej tablica (która jest wskaźnikiem) będzie przypisywana liczha całkowita, co od razu spowoduje błąd kompilacji (a przynajmniej ostrzeżenie), dzięki czemu będzie można szybko poprawić kod programu. Rzutowanie jest konieczne tylko w języku C++, gdzie konwersja z void* na inne typy wskaźnikowe nie jest domyślna, ale język ten oferuje nowe sposoby alokacji
Teraz rozważmy sytuację, gdy zdecydujemy się zwiększyć dokładność' obliczeń i zamiast typu float użyć typu double. Będziemy musieli wyszukać wszystkie wywołania funkcji malloc, calloc i realloc odnoszące się do naszej tablicy i zmieniać wszędzie sizeof (float) na sizeof (double). Aby temu zapobiec lepiej od razu użyć sizeof ‘tablica (lub jeśli ktoś woli z nawiasami: sizeof (‘tablica)). wówczas zmiana typu zmiennej tablica na double* zostanie od razu uwzględniona przy alokacji pamięci.
Dodatkowo, należy sprawdzić, czy funkcja malloc nie zwróciła wartości NULI, dzieje się tak, gdy zabrakło pamięci. Ale uwaga: może się tak stać również jeżeli jako argument funkcji podano zen).
Jeśli dany obszar pamięci nie będzie już nam więcej potrzebny powinniśmy go zwolnić, aby system operacyjny mógł go przydzielić innym potrzebującym procesom. Do zwolnienia obszaru (lamięci używamy funkcji free(), która przyjmuje tylko jeden argument wskaźnik, który otrzymaliśmy w wyniku działania funkcji nalloc().
free (addr);
Należy pamiętać o zwalnianiu pamięci — inaczej dojdzie do tzw. wycieku pamięci — program będzie rezerwowa! nową pamięć ale nie zwracał jej z powrotem i w końcu pamięci może mu zabraknąć.
Należy też uważać, by nie zwalniać dwa razy tego samego miejsca. Po wywołaniu free wskaźnik nie zmienia wartości, pamięć wskazywana przez niego może też nie od razu ulec zmianie. Czasem możemy więc korzystać ze wskaźnika (zwłaszcza czytać) po wywołaniu free nie orientując się, że robimy coś źle i w pewnym momencie dostać komunikat o nieprawidłowym dostępie do pamięci. Z tego powodu zaraz po wywołaniu funkcji free można przypisać wskaźnikowi wartość 0.
Czasami możemy potrzel>ować zmienić rozmiar już przydzielonego bloku pamięci. Tu z pomocą przychodzi funkcja realloc:
tablica = realloc(tablica, 2‘rozmiar‘sizeof ‘tablica);
Funkcja ta zwraca wskaźnik do bk)ku pamięci o pożądanej wielkości (lub NUI.I, gdy zabrakło pamięci). Uwaga może to być inny wskaźnik. Jeśli zażądamy zwiększenia rozmiaru a
za z aa lokowanym aktualnie obszarem nie będzie wystarczająco dużo wolnego miejsca, funkcja znajdzie nowe miejsce i przekopiuje tam starą zawartość. Jak widać, wywołanie tej funkcji może być więc kosztowne |kkI względem czasu.