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
  
felso sarok kategória jobb felso sarok
 

Biológia állatok Fizikai Földrajz Kémia Matematika Növénytan Számítógépes
Filozófia
Gazdaság
Gyógyszer
Irodalom
Menedzsment
Receptek
Vegyes

 
bal also sarok   jobb also sarok
felso sarok   jobb felso sarok
 




































 
bal also sarok   jobb also sarok

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: 2541