8. gyakorlat Pointerek, dinamikus memóriakezelés
Házi ellenőrzés Egy számtani sorozat első két tagja A1 és A2. Számítsa ki a sorozat N- dik tagját! (f0051) Egy mértani sorozat első két tagja A1 és A2. Számítsa ki a sorozat N-dik tagját! (f0053)
Házi ellenőrzés (f0121) Írj egy programot ami kiírja 1-től 12-ig az n! értékét! Kétféle algoritmust készíts! Az elsőben egy külön függvény számítsa ki n! értékét, majd ezt felhasználva a főprogramból írasd ki a megfelelő értékeket. A másik verzióban optimalizáld a programot, és egyetlen ciklus segítségével oldd meg a feladatot!
Feladat (f0215) Futtasd le a cim.c programot, és értelmezd! Melyik érték melyik értékkel egyenlő, és miért?
Pointer A programunk által használt adatok (sőt, maga a program is) a memória egy bizonyos részén tárolódik Ezekre a program a memóriaterület kezdőcímével tud hivatkozni Lehetőségünk van arra, hogy mi is rámutassunk ezekre a lefoglalt területekre ezt pointerekkel tehetjük meg
Mi a pointer? Mutató, egy lefoglalt memóriaterületre mutat Az értéke a memóriaterület címe NEM azonos a memóriaterületen tárolt értékkel! (ld. példák) Létrehozás típus * név; int * p; A pointerekkel kapcsolatos függvények az stdlib.h header fájlban vannak
Pointer operátorok Létrehozás típus * név; int * pa; Hivatkozás feloldása (hová mutat?) *név *pa
Pointer operátorok Cím lekérdezése &név &a A pointer tekinthető egy változónak, ami egy memóriacímet tárol Tehát a pointernek is van egy címe Ez nem azonos azzal, ahova mutat
Feladat (f0216) Fordítsd és futtasd a csere.c programot. Ebben a programban a csere függvény elvileg megcseréli a main függvényben található x és y változó értékét, de valamiért nem működik. Javítsd ki a csere függvény (és a hozzá tartozó hívást) úgy, hogy valóban megcserélje a main két változójának értékét.
Paraméterátadási módok C-ben a függvényeknek a paramétereket két módon adhatjuk át Érték szerint eddig ezt használtuk Cím szerint már láttuk, közvetve
Érték szerinti paraméterátadás Ha meghívunk egy függvényt bizonyos paraméterekkel, akkor a függvényhez csak a paraméterekben tárolt értékek jutnak el A függvény indulásakor új memóriaterület foglalódik a paraméterek számára, ide bemásolódik a kapott érték Ez a paraméter úgy viselkedik, mint egy lokális változó, és csak a függvény végéig él
Cím szerinti átadás A memóriaterület címei abszolútak, tehát bárhol hivatkozunk rá, ugyan azt jelenti Ha a függvénynek nem az éréket adjuk át, hanem annak a változónak a címét, ahol az érték tárolódik, akkor a függvény látni fogja az eredeti memóriahelyet Ezáltal módosíthatjuk függvényből az eredeti értéket
Cím szerinti átadás C-ben Függvény paramétere pointer legyen void csere(int* a, int* b); Függvényen belül az a-t és b-t pointerként használjuk *a = *b; Híváskor ne a változó értékét, hanem annak címét adjuk át csere(&x, &y);
Feladat (f0214) Elemezd és futtasd a pointerek.c programot. Mi a különbség p, q, illetve *p és *q értéke között?
Pointer, dinamikus memória Pointerek használatával lehetőségünk van dinamikusan (futási időben) memóriaterületet foglalni adatok számára Ehhez szükséges függvények: malloc(meret); meret bájt nagyságú területet foglal le, és egy ide mutató, típus nélküli (void) pointert ad vissza
Pointer, dinamikus memória Ha nem tudjuk valaminek a pontos méretét, használhatjuk a sizeof operátort sizeof(int); Az dinamikusan foglalt memóriaterületet fel KELL szabadítani! Egy pointer által mutatott helyen található adatra a * (dereferencia) operátorral hivatkozhatunk (az előbb láttuk) *p = 5; p = 5; /*ez nem ugyan az!*/
Feladat (f0191) Egészítsd ki a malloc-free.c programot úgy, hogy a végrehajtása során ne keletkezzen futási hiba! A 4. sorban inicializáld a változókat! A 6. sorba szúrj be egy utasítást! A kettő közül melyik a helyes megoldás? A másik (önmagában) miért nem jó?
Memória felszabadítás Hagyományos módon lefoglalt memóriát nem szabad felszabadítani automatikus Dinamikusan foglalt memóriát fel kell szabadítani, más nem tudja helyettünk Egy memóriaterületet csak egyszer szabad felszabadítani Ha két pointer mutat ugyan oda, attól az még egy terület Felszabadítani a free() függvénnyel lehet, paraméterben a pointert kell átadni
Feladat (f0217) Nyisd meg a dintomb.c nevű programot, amelyben deklarálunk egy 10 elemű int tömböt és feltöltjük az elemeit a standard inputról, ezután kiíratjuk a tömb elemeit. Deklarálj egy int pointert is, és a beolvasást ennek segítségével valósítsd meg!
Feladat (f0217) Alakítsd át az előző programot úgy, hogy most az első tömbelem értéke előtt kérd be a tömb méretét (a beolvasandó elemek számát). Mi történik, ha 10-nél kisebb értéket, 10-et, 10-nél nem sokkal nagyobb értéket, illetve 10-nél sokkal nagyobb értéket adsz meg elemszámként?
Feladat (f0217) Ezután töröld a tömb deklarációját és az azonosítóját pointerként deklaráld! Az elemszám megadása után de a tömbelemek bekérése előtt dinamikusan foglalj helyet a tömb elemei számára (pontosan annyit, amennyi kell)! Most mi történik, ha tömbméretnek különböző értékeket adsz meg?
Pointerek és tömbök kapcsolata C-ben a tömbök és a pointerek hasonlóan viselkednek A tömb neve ~ pointer A tömb típusa ~ pointer típusa Annyi bájt helyet foglal neki a rendszer, amennyi szükséges az adott típusú, a [] jelek között megadott számú elemhez
Pointerek és tömbök kapcsolata C-ben a tömbök és a pointerek hasonlóan viselkednek A tömb neve a lefoglalt memóriaterület első elemére mutat Amikor a tömböt indexeljük, akkor hasonló ahhoz, mint amikor egy pointert tologatunk a memóriában (ezért 0 az első index, mert abban az esetben nem kell eltolni)
Feladat (f0221) Vizsgáld meg a tombbejaras.c programot. Mi történik, ha a három konstans (N, M és K) értékét megváltoztatod? Vedd N értékét valamivel nagyobbra. Vedd M értékét valamivel nagyobbra. Vedd K értékét valamivel nagyobbra. Vedd K értékét valamivel kisebbre. Mely esetekben hogyan viselkedik a program a futás során? Mi az oka a tapasztalt viselkedésnek?
Több dimenziós tömbök Többdimenziós tömbök esetén az elemek sorfolytonosan vannak a memóriában eltárolva, tehát nem valódi 2D Pl. egy 2x2 -es tömb az négy egymás utáni helyen van Egy 2D tömböt be tudunk járni pointer segítsével úgy, hogy elindulunk a [0][0] helyről (memóriacím kezdete), majd léptetjük egyesével a mutatót
2D tömbök dinamikusan C-ben 2D tömböt dinamikusan két módon hozhatunk létre Sorfolytonosan (ahogy az előbb láttuk) Tömbök tömbjeként
2D tömb sorfolytonosan Ha egy N soros, M oszlopos tömböt szeretnénk létrehozni, akkor foglaljunk le egy egy NxM méretű, egy dimenziós tömböt Ekkor a sorok és oszlopok indexelését nekünk kell kiszámolni Cserébe könnyebb a létrehozás, felszabadítás
2D tömbök dinamikusan Ha 2D tömböt dinamikusan, valódi 2D tömbként szeretnénk kezelni, akkor azt tömbök tömbjeként tehetjük meg, azaz létrehozunk minden sornak egy tömböt Majd egy újabb tömböt, melynek minden eleme egy-egy sorra mutat Felszabadításkor előbb felszabadítjuk a sorokat, majd végül a sorokat tároló fő tömböt
Két hét múlva Egy hét múlva konzultációs óra Nem kötelező bejönni, de nagyon ajánlott Gyakorló feladatok, kérdezési lehetőség Két hét múlva mini ZH a múlt heti anyagból Tömbökkel és sorozatokkal kapcsolatos algoritmikus feladatok Három hét múlva Szemantikai hibajavító feladatok és tömbös algoritmikus feladatok