online kép - Fájl  tubefájl feltöltés file feltöltés - adja hozzá a fájlokat onlinefedezze fel a legújabb online dokumentumokKapcsolat
  
 

Letöltheto dokumentumok, programok, törvények, tervezetek, javaslatok, egyéb hasznos információk, receptek - Fájl kiterjesztések - fajltube.com

Online dokumentumok - kep
  

Mutatók a C programozasi nyelvben: Többszörös indirektségű mutatók. Pointer operatorok, címaritmetika. A mutatók és a tömbök kapcsolata.

számítógépes



felso sarok

egyéb tételek

jobb felso sarok
 
MS Project
Egy tabla létrehozasa - ACCESS
A szöveg alapvető egységei
Kapcsolat az ügyfél szolgalattal
Input perifériak
Az Assemly programozas alapjai: a 80*86 processzor regiszterei, címzési módok, PC megszakítasok, a hadver programozas szintjei
Bűvész programok, utility-k
Adatbazis-típusok
Osztott adatbazisok
Szöveges adatbazisok
 
bal also sarok   jobb also sarok

Mutatók a C programozási nyelvben: Többszörös indirektségű mutatók. Pointer operátorok, címaritmetika. A mutatók és a tömbök kapcsolata.


Általában mutatónak ( a továbbiakban pointer ) nevezzük az olyan változót amely vala­mely objektum címét tartalmazza. C - ben ez az objektum lehet egy egyszerű vál­tozó, tömb, struktúra és függvény is. A pointer definíciója a típusmegadással kez­dôdik. Itt nem a pointer típusáról van szó hanem a­n­nak az objetumnak a típu­-sáról, amelyre a pointer mu­tat. A pointer neve elôtti "*" jelzi, hogy nem egysze­rű változóról van szó, hanem pointe 434d31e r­rôl. Ezután következik a pointer neve. Maga a pointer általában 4 byte hosszú. Ebbôl 2 byte a szegmenscím, 2 byte pedig az offset. Ezalól egyetlen kivétel van : a near ( közeli ) poin­ter amely csak 2 byte hosszú !

Példa : int *px ; // px nevű, integer típusú változóra mutató pointer.

Változó címének átadása az & operátor segítségével

Hogyan adhatjuk át egy változó címét egy pointer változónak ?

Példa : Tekintsük a következô definíciókat :
int x, *px;
px = &x ; // Az & a cím operátor !

Ezen utasítás hatására a px nevű pointer felveszi az x változó címét. Azaz, ha az x változó az 1000 memória címen kezdôdik, akkor a px értéke 1000 lesz. A változó típusának ill. a pointer típusának meg kell egyeznie, vagy típuskonverziót kell alkalmaznunk.


Indirekció.

Indirekciónak nevezzük azt az eljárást, melynek során egy változó értékét nem a változó ne­vé­nek segítségével érjük el, hanem a változóra mutató pointer segítségével. Az indirek­ció operátora a "*" ( csillag ).

Példa : Tekintsük a következô programrészletet :
int x, *px;
x = 2;
px = &x ; // px felveszi x címét. Ezek után a px által mutatott cím tartalmát így iratjuk ki :
printf("\n PX által mutatott cím tartalma = %d", *px) ;
// A képernyôn 2 jelenik meg, az = jel után !

Vigyázat : A "*" használata kettôs jelentésü. A definíciónál azt jelenti hogy a definiált változó pointer lesz. A program során valamely műveletnél, pedig tartalomra való hi­vat­kozást jelent ( Indirekció ! ).

Összefoglaló példa az eddigiekre :

#include <stdio.h>
void main()

Megjegyzés :Természetesen a gyakorlatban ritkán valósul meg az x=y érték­-adás ebben a formában. Az indirekció szemléltetésére azonban kivá­ló­an alkalmas !


Létezik egy speciális eset a pointer értékére vonatkozóan : amikor a pointer a 0 (nulla) értéket tartalmazza. Ekkor beszélünk NULL pointerrôl, aminek a konkrét jelentése az, hogy maga a pointer nem mutat érvényes adatra. A fordító gondosko­dik arról, hogy a <stdio.h>-ban definiált NULL szimbólumhoz tartozó 0 (nulla) érték, ne a nullás memóriahelyet jelentse, nehogy a pointer erre a helyre mutasson. Ez a konstrukció kiválóan alkalmas hibakezelésre, mint azt a file kezelésnél, látni fogjuk !A másik speciális eset egy pointer típusra vonatkozik, aminek a neve void. A void a pointer deklarálásnál azt jelenti, hogy - egyelôre - nincs meghatározott típusa. A void-nak deklarált pointer típusát akkor kell megadni, amikor a pointerrel valami­-lyen műveletet végzünk.

Példa :Tekintsük a következô utasításokat : ( Hasonló a Borland C++ 2.0 helpjében szereplô példához ! )
int i ;
float f ;
void *vp ; // A vp pointernek egyelôre nem ismerjük a típusát ,
// azaz nem tudjuk, hogy milyen típusú változóra mutat
vp = &i ; // vp felveszi az i változó címét.
* ( int * ) vp = 5 ; // vp tartalma 5 lesz, az ( int* ) típusmódosítás, az
// egy­értelmű méret meghatározás miatt szükséges !
vp = &f ; // vp az f változó címét veszi fel.

* ( float * ) vp = 4.8; // itt is szükséges a ( float * ) típusmódosítás !


Egydimenziós tömbök és a pointerek kapcsolata

Ez a kapcsolat már csak azért is érdekes, mert felmerül a kérdés, hogy milyen módon adjunk át egy vektort egy függvénynek. Nyilván nem úgy, hogy egyen­ként átadjuk az ös­szes elemét. Az is kérdéses, hogy egy függvény hogyan adjon vissza         egy vektort. Mint lát­tuk a függvény return-ja után csak egy kifejezés szere­pel­het. Ezen kérdésekre is választ ad a követ­kezô szabály :

Egy egydimenziós vektor neve megegyezik a vektor 0-dik elemének a címével, te­hát a vektor kezdôcímével : vektor = &vektor[0] , ahol "vektor" egy n elemű egydimenziós tömb.


Példa :
int x[10], *px;
px = x; // Egyenértékü a px = &x[0] értékadással. px jelenleg az // x vektor kezdôcímét tartalmazza.

Amennyiben egy vektor kezdôcímét egy azonos típusú pointernek adjuk át, akkor mind a pointer mind a vektor neve a vektor kezdôcímét tartalmazza. A két kifejezés között van azonban egy alapvetô különbség ! A pointer egy változó, a tömb neve pedig egy konstans. Ebbôl következôen, az elôbbi pél­dá­nál maradva :

px++; // Megengedett művelet : A vektor következô elemére mutat.
x++; // Nem megengedett művelet, mert az x konstans !

Ha válaszolni akarunk a feltett kérdésekre, akkor azt mondhatjuk : egy vektort úgy adhatunk át egy függvénynek, hogy a nevét adjuk át aktuális paraméterként. A függ­vénybôl való visszatérés­ esetén pedig a vektor nevével tér vissza a függ­vény. Ennek az esetnek nyilván csak akkor van értelme, ha a függvényben static-nak deklaráljuk a vektort. Itt újabb kérdés merül fel : hogyan hi­vat­kozhatunk a vek­tor kezdô címének ismeretében a vektor tetszôleges elemének címére ill. annak tartalmára. Ezt a kérdést a C nyelv címaritmetikára vonatkozó szabályai­nak is­mere­­tében válaszolhatjuk meg !


Címaritmetika

Egy cím + egész kifejezésnek az az alapvetô tulajdonsága, hogy mindig az illetô cím típusának megfelelôen a következô elemre mutató címet állítja elô.         
&x[2] = x+2; // A vektor 3. elemének a címe = A vektor kezdôcíme + 2
// Általában : &x[i] = x + i
x[2] = *(x+2); // A vektor 3. elemének értéke = Az arra mutató cím
// tartalmával
// Általában : x[i] = *(x + i)

// Buborékrendezés függvénnyel megvalósítva.
#include <stdio.h>
void main()
;
void bubble_sort( int *, int );
int ii;
bubble_sort( a, 10 );
for(ii=0; ii<10; ii++)
printf("\nA[%2d] = %2d",ii,a[ii]);
}
void bubble_sort( int *bs_v, int bs_n )

}

Konkrétan : a bs_v+1 ( vagy bs_v++ ) művelet a bs_v címet két byte-nyival lépteti, ha bs_v egy integer típusú pointer. Ha float vagy double típusú lenne, akkor a léptetés nagysága 4 ill. 8 byte lenne.

További szabályok :

Ha két pointer ugyanannak a tömbnek az elemeire mutat, akkor értelmezettek a <, >, ==, != stb. relációs műveletek.

Ha két pointer ugyanannak a tömbnek az elemeire mutat, ( pl.: a és b ), akkor a - b az a és b közötti elemek darabszámát adja.

Pointerhez hozzáadhatunk, ill. levonhatunk egész számot.

Tilos : Pointerek szorzása, osztása, shiftelése, maszkolása, ill. float vagy double mennyiségek pointerekhez való hozzáadása vagy kivonása.


Kétdimenziós tömbök és a pointerek kapcsolata

Amint megállapítottuk, kétdimenziós tömböt vektorok vektoraként adhatunk meg. A C a mátrixot sorfolytonosan tárolja !

Példa a definícióra :       int y[10][5];

Amíg az egydimenziós tömbök esetén a tömb neve a tömb kezdô elemének a címé­vel egyenlô, kétdimenziós tömbök esetén a tömb neve a tömb kezdô sorának címé­vel egyenlô ! Fizikailag a kezdô elem, ill. a kezdô sor címe megegyezik, csak más a típu­suk : amíg az elôbbi egy integerre mutató pointer, addig az utóbbi egy integer vektor­ra mutató pointer. ( Természetesen a típus mindkét esetben integer ! ) Ez azért lényeges, mert pld. ha az elôbbit eggyel növeljük, akkor egy integernyit lép arrébb a cím, az u­tóbbi esetében az eggyel való növelés egy integer vektornyi léptetést jelent. Ennek a vektornak a méretét nyilván a mátrix oszlopmérete határozza meg.


Példa : Amennyiben a már definiált y tömb után, a következô definíciókat végezzük el :
int (*ppy)[5], *py ; akkor a következôket állapíthatjuk meg :

Az y nem az y tömb kezdô elemének a címe, hanem a kezdô (azaz 0.) sorának - egy öt elemű vektornak - a címe. A ppy egy öt ele­mű egész típusú vektorra mutató pointer , így a következô értékadások helyesek :

ppy = &y[0] ; vagy ppy = y; de a py = y ; rossz, mivel py egy egyszerű változóra mutató pointer !
Az y+1 művelet a következô sor, azaz y[1]-nek a címét állítja elô, tehát ebben az esetben az eggyel való növelés öt integernyi lépte­tést jelentett, mert az oszlopmé­ret öt.A mátrix kezdôelemének a címét a py = &y[0][0]; művelettel helyezhetjük el py-ban. Ekkor a py+1 művelet a mátrix következô elemének a címét állít­ja elô, tehát az y[0][1] elem címét ! Ha adott a mátrix kezdô elemének a címe, akkor egy tetszô­leges elemét a *( py + sorindex*oszlopméret + oszlopindex) m
velet­tel érhet­jük el.



Találat: 2662


Felhasználási feltételek