A kiválasztott változat és az aktuális verzió közötti különbségek a következők.
| Előző változat mindkét oldalon Előző változat Következő változat | Előző változat | ||
| tanszek:oktatas:szamitastechnika:mutatok_pointerek [2022/09/05 21:18] superuser | tanszek:oktatas:szamitastechnika:mutatok_pointerek [2023/11/14 11:10] (aktuális) knehez [Dereferencia] | ||
|---|---|---|---|
| Sor 1: | Sor 1: | ||
| - | **Feladat 1:** Definiáljunk egy változót és írassuk ki azt a címet, ahol éppen tárolva van a memóriában. | + | ==== Pointerek a C nyelvben ==== | 
| + | |||
| + | A pointer a C nyelv egyik kulcsfontosságú fogalma, amely lehetővé teszi a programozók számára, hogy közvetlenül kezeljék/elérjék a memóriát. Más nyelvekben a memória közvetlenül "elérhetetlen" (pl. Java, C#, JavaScript, Python). | ||
| + | |||
| + | A **pointer** //egy memóriacímre mutató változó//, ami lehetővé teszi, hogy közvetlenül hivatkozzunk egy adott memóriaterületre. | ||
| + | |||
| + | ==== Pointer Deklaráció ==== | ||
| + | |||
| + | A pointer deklarációja hasonló a változók deklarációjához, de a típusát is meg kell adni, és a név elé egy **csillagot** írunk. | ||
| + | |||
| + | Például: ha a pointer egy egész szám memóriacímére mutató pointer: | ||
| <code c> | <code c> | ||
| + | int *pointer; | ||
| + | </code> | ||
| + | |||
| + | ==== Pointer inicializálás ==== | ||
| + | |||
| + | A pointer inicializálása a memóriacímmel történik. Például: | ||
| + | <code c> | ||
| + | int variable = 10; | ||
| + | int *pointer = &variable; | ||
| + | </code> | ||
| + | Most a pointer változó a 'variable' memóriacímére mutat. | ||
| + | |||
| + | ==== Dereferencia ==== | ||
| + | |||
| + | A 'dereferenciálás' segítségével elérhetjük a pointer által mutatott értéket. Például: | ||
| + | <code c> | ||
| + | int value = *pointer; | ||
| + | </code> | ||
| + | |||
| + | Most a //value// változó azon értéket tartalmazza, amelyre a //pointer// mutat. | ||
| + | |||
| + | **Feladat 1:** Definiáljunk egy változót és írassuk ki azt a címet, ahol éppen tárolva van a memóriában. | ||
| + | |||
| + | <sxh c> | ||
| #include <stdio.h> | #include <stdio.h> | ||
| - | main() | + | int main() | 
| { | { | ||
| int a = 12; | int a = 12; | ||
| printf("%p\n", &a); | printf("%p\n", &a); | ||
| } | } | ||
| - | </code> | + | </sxh> | 
| - | Megjegyzés: A **printf("%p")** 16-os (hexadecimális) számrendszerben kiírja a címet. A címet a &-jel jelenti. Ha csak 'a'-t írunk akkor 00000C-fog megjelenni, ami a 12 hexadecimális alakja. | + | Megjegyzés: A **printf("%p")** 16-os (hexadecimális) számrendszerben kiírja a címet. Egy változó címét a neve elé írt &-jel jelenti. Ha csak 'a'-t írunk akkor 00000C-fog megjelenni, ami a 12 hexadecimális alakja, azaz a változó értéke, nem a címe lesz. | 
| **Feladat 2:** Definiáljunk egy változót és egy erre a változóra mutató pointert. Írassuk ki a változó értékét a pointer segítségével. | **Feladat 2:** Definiáljunk egy változót és egy erre a változóra mutató pointert. Írassuk ki a változó értékét a pointer segítségével. | ||
| - | <code c> | + | <sxh c> | 
| #include <stdio.h> | #include <stdio.h> | ||
| Sor 24: | Sor 58: | ||
| printf("%d\n", *b); // a b előtti * mutatja, hogy nem a címet, hanem az ott tárolt értéket kell kiíratni | printf("%d\n", *b); // a b előtti * mutatja, hogy nem a címet, hanem az ott tárolt értéket kell kiíratni | ||
| } | } | ||
| - | </code> | + | </sxh> | 
| **Feladat 3:** Az előző feladatban adott b pointer segítségével növeljük meg az **a** változó értékét, majd írassuk ki az **a** változót. | **Feladat 3:** Az előző feladatban adott b pointer segítségével növeljük meg az **a** változó értékét, majd írassuk ki az **a** változót. | ||
| - | <code c> | + | <sxh c> | 
| #include <stdio.h> | #include <stdio.h> | ||
| Sor 41: | Sor 75: | ||
| printf("%d\n", a); | printf("%d\n", a); | ||
| } | } | ||
| - | </code> | + | </sxh> | 
| **Érték növelése pointeren kereszül** | **Érték növelése pointeren kereszül** | ||
| - | <code c> | + | <sxh c> | 
| #include <stdio.h> | #include <stdio.h> | ||
| - | main() | + | int main() | 
| { | { | ||
| int a = 10; | int a = 10; | ||
| Sor 58: | Sor 92: | ||
| printf("%d", a); | printf("%d", a); | ||
| } | } | ||
| - | </code> | + | </sxh> | 
| Nem lett 11 **a** értéke. Miért? Mert (*b)++ -t kellett volna írni. | Nem lett 11 **a** értéke. Miért? Mert (*b)++ -t kellett volna írni. | ||
| Sor 68: | Sor 102: | ||
| Hozzunk létre egy másik pointert ami az első pointerre mutat. Irjuk ki a pointerek által mutatott címen tárolt értéket! | Hozzunk létre egy másik pointert ami az első pointerre mutat. Irjuk ki a pointerek által mutatott címen tárolt értéket! | ||
| - | <code c> | + | <sxh c> | 
| #include <stdio.h> | #include <stdio.h> | ||
| - | main () | + | int main () | 
| { | { | ||
| int val = 10; | int val = 10; | ||
| Sor 84: | Sor 118: | ||
| printf("**pptr = %d\n", **pptr); | printf("**pptr = %d\n", **pptr); | ||
| } | } | ||
| - | </code> | + | </sxh> | 
| **Érdekesség: Jelszó feltörés** | **Érdekesség: Jelszó feltörés** | ||
| Sor 90: | Sor 124: | ||
| Az alábbi program bekér egy karaktert a felhasználótól. Ha nem c-t nyom akkor nem helyes a kódja.  | Az alábbi program bekér egy karaktert a felhasználótól. Ha nem c-t nyom akkor nem helyes a kódja.  | ||
| - | <code c> | + | <sxh c> | 
| #include <stdio.h> | #include <stdio.h> | ||
| - | main() | + | int main() | 
| { | { | ||
| char kod; | char kod; | ||
| Sor 117: | Sor 151: | ||
| } | } | ||
| - | </code> | + | </sxh> | 
| - | + | ||
| - | Látva a kódot, ha tegyük fel 8db bármilyen karaktert ütünk be, akkor is rendszergazdák leszünk. Magyarázzuk meg miért? (azért, mert a scanf felülírja a memóriát és a "helyes" érték 0-ja felülíródik. Ezt nevezzük "buffer túlcsordulásos" támadásnak. | + | |
| + | Látva a kódot, ha tegyük fel 5db bármilyen karaktert ütünk be, akkor is rendszergazdák leszünk. (érdemes kikísérletezni hány darab leütés kell, hogy elromoljon a működés) Magyarázzuk meg miért? (azért, mert a scanf felülírja a memóriát és a "helyes" érték 0-ja felülíródik. Ezt nevezzük "buffer túlcsordulásos" támadásnak. | ||