motzel.online
Strona domowaBogdana Modzelewskiego
Nowości
Kurs języka C
Pliki
Linki
e-mail
wizyt od 99.09.01
Najlepiej przeglądać w rozdzielczości 1024x768
15.4. Dynamiczny przydział pamięci
Pamiętasz tablice, prawda ? Wielkość tablicy musiała być ustalona już w momencie pisania programu. W przypadku prostych programów nie
jest to problemem, ale co zrobić, gdy potrzebną wielkość tablicy będzie można określić dopiero po uruchomieniu programu ? Na przykład dane
o pracownikach jakiejś firmy mają być odczytywne z pliku - w takim przypadku, aż do momentu otwarcia pliku wielkość ta nie jest znana. Można
co prawda zadeklarować tablicę o wielkości dużo większej niż to prawdopodobnie będzie potrzebne, ale wiaże się z tym duże marnotrawstwo
pamięci. Poza tym może okazać się, że w pewnym momencie wielkość ta i tak nie będzie wystarczająca. Z pomocą przychodzą nam wskaźniki
i możliwość, którą udostępniają a mianowicie dynamiczny (czyli już w trakcie pracy programu) przydział pamięci operacyjnej. Ich zastosowanie
do tego celu pokażemy jak zwykle na przykładowym programie. Aby nie wprowadzać niepotrzebnego zamieszania zdecydowałem się dokonać
przeróbki programu już analizowanego (w podpunkcie poświeconemu tablicom struktur). Omówione zostaną tu tylko różnice. A oto program:
Kod źródłowy programu
Pierwsza różnica jest już przy dołączają plików nagłówkowych. Oprócz "standardowego" stdio.h
dołączamy jeszcze stdlib.h. Plik ten zawiera deklaracje nowych funkcji, które użyjemy w naszym programie -
malloc oraz free. Przejdźmy dalej - mamy tu deklarację struktury o
nazwie PRACOWNIK, następnie zmiennej i. W następnej linijce natykamy się na następną różnicę -
zamiast trzyelementowej tablicy struktur typu PRACOWNIK deklarujemy tu wskaźnik na strukturę typu PRACOWNIK. Następna linijka zawiera
już całkiem nową rzecz - wywołanie funkcji malloc. Funkcja ta alokuje (przydziela dla programu) pamięć
operacyjną o wielkości podanej przy wywołaniu (w bajtach). W naszym przypadku każemy przydzielić jej pamięć o wielkości
"3 * sizeof(PRACOWNIK)". Jak zapewne pamiętasz operator sizeof zwraca wielkość w bajtach podanego
parametru. Tak więc wynika z tego, że kazaliśmy funkcji malloc przydzielić tyle pamięci, aby zmieściły się
w niej trzy struktury typu PRACOWNIK. Funkcja ta, w przypadku gdy przydział pamięci się powiódł, zwraca adres pierwszego zaalokowanego
bajtu pamięci. Ponieważ nasz wskaźnik o nazwie kadra wskazuje na strukturę PRACOWNIK, a funkcja
malloc zwraca wskaźnik typu void* to musimy jeszcze dokonać
rzutowania. Rzutowanie wskażników robi się w ten sam sposób jak rzutowanie typów prostych - jedynym wyjątkiem jest dodanie gwiazdki za
nazwą typu. Tak więc, aby dokonać rzutowania wskaźnika typu void* na wskaźnik na strukturę
PRACOWNIK musimy dodać jeszcze "(PRACOWNIK*)" i dopiero teraz możemy przypisać ten adres naszej zmiennej. Jak już do tego doszliśmy
to wyjaśnię jeszcze zastosowanie wskaźnika na void. Jak zapewne pamiętasz słowo kluczowe void
określa brak typu. Nie można deklarować zmiennych typu void, jedynym dopuszczalnym miejscem, gdzie można go użyć jest określenie typu,
który zwraca funkcja. Natomiast wskaźnika na void jak najbardziej można używać i na dodatek jest on
bardzo przydatny. Możesz więc zadeklarować sobie zmienną typu wskaźnik na void. Bardzo ważną zaletą tego wskaźnika jest to, że możesz
dokonać przypisania na niego dowolnego innego wskaźnika. Oczywiście, z uwagi na to, że typ na który on wskazuje nie jest określony nie
możesz dokonywać na nim operacji arytmetycznych. Dobrze to taka mała dygresja, wróćmy do analizy naszego programu. Otóż napisałem, że
funkcja malloc zwraca nam adres przydzielonego bloku pamięci. Co jednak jest w sytuacji, gdy przydział
pamięci nie jest możliwy np. w sytuacji, gdy próbujemy sobie zaalokować 100 MB pamięci na komputerze wyposażonym w tylko 32 MB
(pomijam tu istnienie pamięci wirtualnej). Otóż w takim przypadku zamiast adresu zwrócona zostaje wartość
NULL. Jest to specjalnie zadeklarowana wartość mówiąca o tym, że wskaźnik jest pusty (czyli nie
wskazuje na żadne dane). Dlatego, aby zabezpieczyć się przed używaniem pamięci, która nie została nam przydzielona należy zaraz po
wywołaniu tej funkcji sprawdzić wartość, która zostałą zwrócona. Dokonujemy tego w następnej linijce. W naszym przypadku w sytuacji, gdy
przydział pamięci nie był możliwy wypisujemy tylko na ekranie odpowiedni komunikat i wychodzimy z programu. Program możemy zakończyć
w dowolnym momencie przy użyciu funkcji exit. Jedynym jej parametrem jest kod wyjścia, który zostanie
przekazany do systemu operacyjnego. W przypadku, gdy nasz program nie będzie używany w plikach wsadowych nie jest on ważny. Skoro już
udało nam się przydzielić pamięć i jesteśmy tego pewni to musimy wpisać do niej jakieś dane. W naszym programie będą to dane o
pracownikach naszej firmy. Przypisania dokonujemy w taki sposób jak przedstawione to było w poprzednich podpunktach. W następnych
trzech linijkach programu wyświetlamy dopiero co wpisane dane. Zauważ tu, że mimo tego, że zmienna
kadra jest wskaźnikiem to uźywamy jej tu tak samo jakby była tablicą. Wynika to z zależności między
wskaźnikami a tablicami przedstawionymi w jednym z poprzednich podpunktów kursu. W ostatniej linijce programu mamy do czynienia z
drugą większą nowością - funkcją free. Funkcja ta zwraca do systemu przydzielona wcześniej przy pomocy
funkcji malloc pamięć. Mimo, że w tym przypadku nie musieliśmy tego robić bo przy wyjściu z programu
pamięć ta zostałaby automatycznie zwrócona, to jednak do dobrego zwyczaju programistycznego należy zwrócenie wszystkich zaalokowanych zasobów.
Pamiętaj, że po zwolnieniu pamięci nie możesz już używać tego obszaru pamięci ! Teoretycznie możesz go modyfikować (bo ciągle masz do
niego wskaźnik), ale nie powienineś, gdyż system operacyjny mógł przydzielić tą pamięć innemu programowi i takie grzebanie po zasobach
drugiego programu może zakończyć tym, że program ten (lub nawet cały system) się zawiesi. W systemach operacyjnych z ochroną pamięci
natomiast może to spowodować błąd ochrony i niekontrolowane wyjście z twojego programu z błędem ("Program wykonał niedozwoloną
operację..." ;-)
[<< Wskaźniki do struktur | Spis treści | Operacje na ciągach znaków >>]
Wyszukiwarka
Podobne podstrony:
15 315Program wykładu Fizyka II 14 1515 zabtechnŁódzkiego z311[15] Z1 01 Wykonywanie pomiarów warsztatowych15 Wykonywanie rehabilitacyjnych ćwiczeń ortoptycznychid24710 15 5815 7 2012ComboFix 15 1 22 2 2015rBrother 324 [CT] DQ08 15więcej podobnych podstron