**1. feladat:** Milyen hibákat talál az alábbi megoldásokban? m = malloc(80); m = NULL; **megoldás**: 80 bájt lefoglalása, majd a pointer nullázása. Probléma: - a lefoglalt 80 byte nem szabadul fel. ''m = NULL'' sor természetesen nullázza az ''m'' mutatót, de ettől még a 80 bájt lefoglalva marad. ---- Egy pointerhez memória lefoglalása majd amikor már nincs rá szükség, akkor a felszabadítása az alábbi váz alapján valósítható meg. m = malloc(80); // számolás.. egyéb kódok free(m); ---- Nézzük a következő hibás példát. Mi lehet a hiba? free(n); n = 5; **megoldás**: felszabadított memóriaterületre akarunk írni. Ha már meghívtuk a free() memória felszabadító függvényt, akkor nem lehet tovább használni a pointert. (ameddig a malloc()-al újra foglalunk neki memóriát.) ---- A következő példában nem használunk dinamikus memóriafoglalást, ami elvileg még jó is lehet, de mégsem szabályos. Miért? char *p; *p = 'a'; **megoldás**: nem inicializált pointert akarunk használni. Azaz a ''char *p'', nem ad értéket a ''p'' pointernek, csak helyet foglal neki, és azon a helyen 0 van, vagy valami memóriaszemét. Ha a következő sorban a '' *p = 'a' ''-val a p által mutatott címre bele szeretnénk másolni a 'a'-t akkor az nem lesz lehetséges, mert a 0-ás címre nem írhatunk. ---- **Feladat:**: foglaljunk le dinamikusan egy 10 elemű int vektort. #include int main() { int *v = (int *)malloc(1000 * sizeof(int)); free(v); return 0; } A kód igazából nem csinál túl sok használhatót, csak demonstrálja a malloc() használatát. A paramétere azt jelenti, hogy hány bájtot szeretnénk lefoglalni. Önmagában 1000-el meghívva csak 250 darab int értéknek foglal helyet, mert minden ''int'' 4 byte-ot foglal. Mivel ezt nem akarjuk fejből tudni ezért használjuk a beépített sizeof() operátort, ami sizeof(int) esetén 4-et ad vissza. Összefoglalva az 1000 int lefoglalásához 4000 byte-ok kell lefoglalni. ---- **Feladat:**: Az alábbi 3 függvényből melyik helyes, illetve hibás? int* f(void) { int x = 10; return (&x); } int* g(void) { int * p; *p = 10; return p; } int* h(void) { int *p; p = (int *) malloc (sizeof(int)); return p; } **megoldás**: csak a h() függvény helyes. A f() és g() hibásak, mert ezekben az esetekben a memóriacím a veremben jön létre és a visszaadott érték helytelen memóriacímre fog mutatni. Az f() és g() esetén lokális változókat hozunk létre, és ezekre mutató memóriacímet adunk vissza. A függvény használatakor, a használat után ezek a memóriacímek nem használhatók tovább. A h() esetén is a p változó lokális lesz, az is megszűnik a függvény használata után, de a malloc() által visszaadott memória cím (mint számérték továbbra is használható) a ''return p'' itt is nem a p-t, hanem a p-ben tárolt címet adja vissza, ami a h() esetén továbbra is használható. //A példa azt mutatja, hogy a malloc() által létrehozott cím és a mögötte lefoglalt memória globális, nem számít hol hívtuk meg.// ---- **Feladat:**: Mi lesz az alábbi program kimenete? #include void f(int *a) { a = (int*)malloc(sizeof(int)); } int main() { int *p; f(p); *p = 10; printf("%d",*p); } **megoldás**: nem ír ki semmit, hanem lefagy. ---- **Feladat:**: Hogyan lehetne kijavítani az előző feladatban szereplő programot? **megoldás**: az előző program azért nem működik, mert a pointer nincs inicializálva (csak egy másolat), ezért a 0-s memóriacímet adja át az f() függvénynek, így a malloc lefoglalja a 4 byte-ot, de hibás helyre írja vissza. A javítás során vegyük figyelembe, hogy egy pointerre mutató pointer már ténylegesen a p változó címét adja vissza, amibe már a f() malloc()-ja már be tudja írni a lefoglalt memória címét. #include void f(int **a) { *a = (int*)malloc(sizeof(int)); } int main() { int *p; f(&p); *p = 10; printf("%d",*p); } ---- **Feladat:**: Mi a probléma következő programmal? #include int main() { float *p = (float *)malloc(sizeof(float)); p = NULL; free(p); } **megoldás**: a p NULL-ázása után, a free() nem tudja, hogy hol van az a memóriacím, amit fel kell szabadítani, a free() igazából nem egy változót magát, hanem a benne tárolt memória címet (mint számértékhez tartozó foglalást) szünteti meg.) Más szóval: a free() nem a p változót, hanem az abban tárolt címet szabadítja fel. ===== Ellenőrző kérdések ===== **Mi a helyes deklarációja egy int típusra mutató pointernek?** A) int p*; B) int *p; C) pointer int p; D) int &p; Megoldás: B ---- **Hogyan lehet helyesen lefoglalni memóriát egy 10 elemű int tömbnek dinamikusan?** A) int *arr = malloc(10); B) int arr = malloc(10 * sizeof(int)); C) int *arr = malloc(10 * sizeof(int)); D) int arr[10] = malloc(sizeof(int)); Helyes válasz: C ---- **Mi lesz az eredmény?** int array[] = {100, 200, 300}; int *ptr = array; printf("%d", *(ptr++)); printf("%d", *ptr); A) 100200 B) 200300 C) 100100 D) 200200 Megoldás: A. *(ptr++) előbb kiírja a 100-at, majd eggyel tovább lépteti a pointert. A következő kiírás már a 200-ra mutat. ---- **Melyik állítás igaz az alábbiak közül?** A) Egy pointer típusa nem függ attól, hogy milyen adatra mutat. B) Egy pointer mindig egész számot tárol. C) Pointerek aritmetikája nem megengedett C-ben. D) Egy pointer típusa meghatározza, hogy milyen típusú adatot érhetünk el rajta keresztül. Helyes válasz: D ---- **Mi lesz az eredmény?** int x = 5, y = 10; int *p = &x; int *q = &y; *p = *q; printf("%d %d", x, y); A) 5 10 B) 10 10 C) 5 5 D) 10 5 Helyes válasz: B. ---- **Mire mutat a p pointer a következő deklaráció után?** int arr[10]; int *p = arr; A) Az arr tömb első elemére B) Az arr tömb utolsó elemére C) Az arr tömb méretére D) Véletlenszerű memória címre Megoldás: A ---- **Mi a hiba a következő kódrészletben?** int num = 20; int *ptr; *ptr = num; A) Érvénytelen pointer-dereferencia (nem inicializált pointer) B) Szintaktikai hiba C) Hiányzó pontosvessző D) A num változó helytelen típusa Megoldás: A ---- **Mi lesz a következő kód kimenete?** char *str = "Hello"; printf("%c", *(str+1)); A) H B) e C) l D) o Megoldás: B ---- **Mit jelent, ha egy pointer NULL értékű?** A) A pointer érvényes memória címre mutat B) A pointer egy egész számot tárol C) A pointer nem mutat érvényes memória címre D) A pointer konstans értékre mutat Megoldás: C ---- **Mi lesz a következő kód kimenete?** int a[] = {2, 4, 6, 8}; int *p = a; printf("%d", *(p + 2)); A) 2 B) 4 C) 6 D) 8 Megoldás: C ---- **Melyik operátor adja vissza egy változó memória-címét?** A) * B) & C) % D) # Megoldás: B ---- **Mit ír ki a következő programrészlet?** int x = 5; int *p = &x; *p = 10; printf("%d", x); A) 5 B) 0 C) 10 D) véletlenszerű érték Megoldás: C , mivel az x értéke megváltozik a pointeren keresztül