Dynamická alokácia alebo "Mega pamäte, prosím".

Polia sú veľmi užitočný nástroj. V tej forme, v akej ich zatiaľ poznáme ale majú jednu drobnú slabinu -- dopredu treba vedieť, aké budú veľké. Keď určujeme ich veľkosť, nemôžeme používať premenné, musí tam byť nejaké dopredu známe číslo. Všetkým premenným a poliam, ktoré sú klasicky deklarované, sa vytvorí miesto v pamäti hneď na začiatku. A potom už žiadna premenná nepribudne a žiadne pole sa nemá šancu zväčšiť či zmenšiť. Pamäť je ale dosť veľká a niekedy až počas behu programu zistíme, že by sme z nej ešte kúsok potrebovali.

Samozrejme -- dá sa to. Ale treba dávať na nejaké veci pozor. Keď si necháme dočasne nejakú pamäť prideliť, použijeme ju a už pre nás nie je potrebná, musíme ju zas uvoľniť. Keby sme to totiž nespravili, pamäť by nám ostala pridelená až dovtedy, kým by program nedobehol. A ostatné programy, ktoré v systéme bežia by ju nemohli použiť.

Takže ako sa to robí. Ak chceme používať funkcie, ktoré pracujú s pamäťou, musíme najprv načítať jeden nový halvičkový súbor -- stdlib.h. Spravíme to rovnako ako s jeho kolegom: #include <stdlib.h>. (Keď okrem toho ešte chcete písať na terminál, musíte samozrejme pridať aj #include <stdio.h>.) Teraz môžete používať funkciu malloc (z anglického memory allocation -- alokácia pamäte). Funkcii zadáte parameter, koľko bajtov pamäte chcete a ona vám vráti smerník na začiatok bloku pamäte (alebo vráti nulový smerník NULL, ak pamäť nie je k dispozícii). Takže ak by som zrazu potreboval pole 100 celých čísel, zariadim si to takto:

    int *smernik;
    smernik = (int *) malloc(100 * sizeof(int));
    smernik[23] = 145;

V tom, čo sme tu predviedli sú dve podivné veci. Prvá je to (int *) pred funkciou malloc. Na čo to tam je? Totiž funkcia malloc nevráti smerník na int, ale "smerník všeobecný" teda smerník na void. No a kompilátor si pamätá, ktorý smerník na čo ukazuje a keby sme chceli tento všeobecný smerník priradiť do premennej smernik, kompilátor by nám vynadal, že to nemôžeme priradiť, lebo ten druhý smerník je iného typu. Typ smerníku sa ale dá meniť. Na to slúži vec zvaná pretypovanie, ktorú vidíte vyššie. Skrátka sa pred smerník napíše jeho nový typ a kompilátor potom to priradenie zožerie.

Ďalšia novinka je to sizeof(int). Ako sme už povedali, funkcia malloc nám vyhradí toľko bajtov, koľko si zažiadame. Keby sme napísali iba malloc(100), dostali by sme 100 bajtov. Problém je v tom, že jeden int zaberie viac než jeden bajt (v závislosti od kompilátora to bývaju väčšinou 2 alebo 4 bajty). A na to, aby sme zistili koľko je to vo vašom systéme, slúži direktíva sizeof, ktorá vie zistiť, koľko bajtov nejaký dátový typ zaberá.

Akonáhle vieme, že už takto pridelenú pamäť nebudeme používať, musíme ju uvolniť. Spravíme to takto:

    free((void *) smernik);

Funkcia free musí na vstupe dostať smerník na začiatok pridelenej pamäte (z toho vyplýva, že by sme smernik počas používania nemali ničím prepísať, lebo by sme už nemali odkiaľ zistiť, ktorú časť pamäte uvoľňujeme). Funkcia free chce na vstupe smerník typu void a tak sme ten náš museli pretypovať.

Nasledujúci program zistí koľko megabajtov pamäte je nám systém ochotný dať k dispozícii. (Pamäť v ňom hanebne neuvoľňujeme a začiatky blokov si nepamätáme -- tentokrát to zveríme operačnému systému.)

    #include <stdio.h>
    #include <stdlib.h>
    
    main()
    {
        int i = 0;
	
        while(malloc(1000000) != NULL)
            i++;

        printf("K dispozicii je %d MB pamate\n",i);
    }

Takže úlohy:

Úloha č.1 Pochopte, napíšte a skompilujte predchádzajúcu ukážku.

Úloha č.2 Napíšte program, krorý vypíše, koľko bajtov zaberajú premenné typu int, float, char, (int *), (float *) a (char *).

Úloha č.3 Do premennej velkost typu int načítajte hodnotu, nechajte si prideliť pole intov danej veľkosti (nezabudnite si dopredu vytvoriť smerník tak, ako je to v prvej ukážke), naplňte ho na striedačku nulami a jedničkami, vypíšte ho a uvoľnite pamäť.

Úloha č.4 Napíšte program, ktorý alokuje pole intov veľkosti 100, spomedzi čísel, ktoré v ňom budú (nejaké náhodné bláboly z pamäte) nájde a vypíše najmenšie číslo a pamäť znova uvolní. (Varianta pre guruov - to sú tí, čo majú aspoň 18 bodov: program nájde najmenšie kladné číslo. Ak sú všetky záporné, napíše to.)

Anino Belan 2003-10-26