Mi a mutató a C-ben?
A C mutatója egy olyan változó, amely egy másik változó címét tárolja. A mutató egy másik mutatófunkcióra is hivatkozhat. A mutató növelhető / csökkenthető, azaz a következő / előző memóriahelyre mutat. A mutató célja a memóriamegtakarítás és a gyorsabb végrehajtási idő elérése.
Hogyan használjuk a mutatókat a C-ben
Ha deklarálunk egy int típusú v változót, akkor v ténylegesen tárol egy értéket.
v most nullával egyenlő.
Azonban minden változónak, az értéken kívül, megvan a címe is (vagy egyszerűen megfogalmazva, ahol a memóriában található). A cím lekérhető úgy, hogy egy ampersandot (&) tesz a változó neve elé.
Ha egy változó címét kinyomtatja a képernyőn, az teljesen véletlenszerű számnak fog kinézni (ráadásul a futtatásonként eltérő lehet).
Próbáljuk ki ezt a gyakorlatban a C példa mutatójával
A program kimenete -480613588.
Mi az a mutató? Érték tárolása helyett egy mutató y eltárolja egy változó címét.
Mutató változó
Int * y = & v;
VÁLTOZÓ |
MUTATÓ |
A érték alatt a megnevezett / memória címe |
A változó , hogy pont, hogy a tároló / memória címét egy másik változó |
Mutató kijelentése
A változókhoz hasonlóan a C programozás mutatóit is deklarálni kell, mielőtt felhasználhatók lennének a programban. A mutatók bármit megnevezhetnek, amire vágynak, amennyiben betartják C névadási szabályait. A mutató nyilatkozatának formája a következő.
data_type * pointer_variable_name;
Itt,
- Az data_type a C változótípusainak mutató alaptípusa, és jelzi annak a változónak a típusát, amelyre a mutató mutat.
- A csillag (*: ugyanaz a szorzáshoz használt csillag), amely indirection operátor, egy mutatót jelent.
Nézzünk meg néhány érvényes mutató deklarációt ebben a C mutató oktatóanyagban:
int *ptr_thing; /* pointer to an integer */int *ptr1,thing;/* ptr1 is a pointer to type integer and thing is an integer variable */double *ptr2; /* pointer to a double */float *ptr3; /* pointer to a float */char *ch1 ; /* pointer to a character */float *ptr, variable;/*ptr is a pointer to type float and variable is an ordinary float variable */
Inicializálja a mutatót
A mutató deklarálása után inicializáljuk, mint a szokásos változókat változó címmel. Ha a C programozás mutatóit nem inicializálják és nem használják a programban, az eredmények kiszámíthatatlanok és potenciálisan katasztrofálisak.
Egy változó címének megszerzéséhez használjuk az ampersand (&) operátort, amely egy olyan változó neve elé kerül, amelynek címére szükségünk van. A mutató inicializálása a következő szintaxissal történik.
Mutatószintaxis
pointer = &variable;
Az alábbiakban egy egyszerű programot mutatunk a mutató szemléltetésére:
#includeint main(){int a=10; //variable declarationint *p; //pointer variable declarationp=&a; //store address of variable a in pointer pprintf("Address stored in a variable p is:%x\n",p); //accessing the addressprintf("Value stored in a variable p is:%d\n",*p); //accessing the valuereturn 0;}
Kimenet:
Address stored in a variable p is:60ff08Value stored in a variable p is:10
Operátor | Jelentése |
* | 2 célt szolgál
|
& | Csak 1 célt szolgál
|
A mutatók típusai C-ben
Az alábbiakban bemutatjuk a C különböző típusú mutatóit :
Null Pointer
Null pointert hozhatunk létre úgy, hogy a point deklaráció során null értéket rendelünk hozzá. Ez a módszer akkor hasznos, ha a mutatóhoz nincs hozzárendelve cím. A null mutató mindig 0 értéket tartalmaz.
A következő program egy null mutató használatát szemlélteti:
#includeint main(){int *p = NULL; //null pointerprintf(“The value inside variable p is:\n%x”,p);return 0;}
Kimenet:
The value inside variable p is:0
Üres mutató
A C programozásban az érvénytelen mutatót általános mutatónak is nevezik. Nincs szabványos adattípusa. A void kulcsszó használatával egy érvénytelen mutató jön létre. Bármely változó címének tárolására használható.
A következő program az érvénytelen mutató használatát szemlélteti:
#includeint main(){void *p = NULL; //void pointerprintf("The size of pointer is:%d\n",sizeof(p));return 0;}
Kimenet:
The size of pointer is:4
Vad mutató
A mutató akkor vad jelző, ha nem inicializáljuk semmire. Az ilyen típusú C-mutatók nem hatékonyak, mert valamilyen ismeretlen memóriahelyre utalhatnak, ami problémákat okozhat a programunkban, és a program összeomlásához vezethet. Mindig óvatosnak kell lennie, amikor vad mutatókkal dolgozik.
A következő program szemlélteti a vad mutató használatát:
#includeint main(){int *p; //wild pointerprintf("\n%d",*p);return 0;}
Kimenet
timeout: the monitored command dumped coresh: line 1: 95298 Segmentation fault timeout 10s main
A c-ben található más típusú mutatók a következők:
- Csüngő mutató
- Komplex mutató
- Közel mutató
- Távoli mutató
- Hatalmas mutató
Közvetlen és közvetett hozzáférési mutatók
A C-ben két egyenértékű módja van a változó tartalom elérésének és kezelésének
- Közvetlen hozzáférés: közvetlenül használjuk a változó nevét
- Közvetett hozzáférés: a változóra mutatót használunk
Értsük meg ezt az alábbi program segítségével
#include/* Declare and initialize an int variable */int var = 1;/* Declare a pointer to int */int *ptr;int main( void ){/* Initialize ptr to point to var */ptr = &var;/* Access var directly and indirectly */printf("\nDirect access, var = %d", var);printf("\nIndirect access, var = %d", *ptr);/* Display the address of var two ways */printf("\n\nThe address of var = %d", &var);printf("\nThe address of var = %d\n", ptr);/*change the content of var through the pointer*/*ptr=48;printf("\nIndirect access, var = %d", *ptr);return 0;}
A program hibátlan fordítása után az eredmény:
Direct access, var = 1Indirect access, var = 1The address of var = 4202496The address of var = 4202496Indirect access, var = 48
A mutató számtana a C-ben
A mutató műveleteit az alábbi ábra foglalja össze
Kiemelt művelet (elsőbbség)
A C mutatókkal végzett munka során a következő prioritási szabályokat kell betartanunk:
- Az * és & operátoroknak ugyanaz az elsőbbségük, mint az unár operátoroknak (a tagadás!, A növekmény ++, a dekrement--).
- Ugyanebben a kifejezésben az unáris operátorokat *, &,!, ++, - jobbról balra értékelik.
Ha egy P mutató egy X változóra mutat, akkor a * P mindenütt használható, ahol X beírható.
A következő kifejezések egyenértékűek:
int X = 10 int * P = & Y; A fenti kód esetében az alábbi kifejezések igazak | |
Kifejezés | Egyenértékű kifejezés |
Y = * P + 1 * P = * P + 10 * P + = 2 ++ * P (* P) ++ | Y = X + 1 X = X + 10 X + = 2 ++ X X ++ |
Ez utóbbi esetben zárójelekre van szükség: mivel az * és ++ operátorokat jobbról balra értékelik, zárójelek nélkül a P mutató növekszik, nem pedig az az objektum, amelyre a P rámutat.
Az alábbi táblázat a C-mutatók kezelésénél használható számtani és alapműveletet mutatja
Művelet | Magyarázat |
Feladat | int * P1, * P2 P1 = P2; P1 és P2 ugyanazon egész változóra mutat |
Növekedés és csökkentés | Int * P1; P1 ++; P1--; |
Eltolás hozzáadása (állandó) | Ez lehetővé teszi, hogy a mutató N elemet mozgasson egy táblázatban. A mutató a változó típusának bájtjainak N-szeresével növekszik vagy csökken. P1 + 5; |
C mutatók és tömbök példákkal
Hagyományosan a tömb elemeihez az indexe alapján férünk hozzá, de ez a módszer pointerek segítségével kiküszöbölhető. A mutatók megkönnyítik az egyes tömb elemek elérését.
#includeint main(){int a[5]={1,2,3,4,5}; //array initializationint *p; //pointer declaration/*the ptr points to the first element of the array*/p=a; /*We can also type simply ptr==&a[0] */printf("Printing the array elements using pointer\n");for(int i=0;i<5;i++) //loop for traversing array elements{printf("\n%x",*p); //printing array elementsp++; //incrementing to the next element, you can also write p=p+1}return 0;}
Kimenet
12345
Ha egy mutatóhoz hozzáad egy adott számot, a mutató helye az összeadási művelettel kapott értékre kerül. Tegyük fel, hogy p olyan mutató, amely jelenleg a 0 memóriahelyre mutat, ha az összeadási műveletet (p + 1) követjük, akkor a következő módon fog végrehajtani:
Mivel p jelenleg 1 hozzáadása után a 0 helyre mutat, az érték 1 lesz, és ezért a mutató az 1 memória helyére mutat.
C mutatók és húrok példákkal
A karakterlánc a char objektumok tömbje, amelynek null karaktere „\ 0”. A karakterláncokat manipulálhatjuk mutatók segítségével. Ez a C példa mutatója elmagyarázza ezt a szakaszt
#include#include int main(){char str[]="Hello Guru99!";char *p;p=str;printf("First character is:%c\n",*p);p =p+1;printf("Next character is:%c\n",*p);printf("Printing all the characters in a string\n");p=str; //reset the pointerfor(int i=0;i Kimenet
First character is:HNext character is:ePrinting all the characters in a stringHelloGuru99!A húrok kezelésének másik módja egy mutatósáv, például a következő programban:
#includeint main(){char *materials[ ] = { "iron", "copper", "gold"};printf("Please remember these materials :\n");int i ;for (i = 0; i < 3; i++) {printf("%s\n", materials[ i ]);}return 0;} Kimenet:
Please remember these materials:ironcoppergoldA mutatók előnyei C-ben
- A mutatók hasznosak a memóriahelyek eléréséhez.
- A mutató hatékony módot kínál a tömbstruktúra elemeinek elérésére.
- A mutatókat dinamikus memória-allokációra, valamint üzletkötésre használják.
- A mutatók komplex adatstruktúrák, például összekapcsolt lista, grafikon, fa stb. Létrehozására szolgálnak.
A mutatók hátrányai C-ben
- A mutatók megértése kissé összetett.
- A mutatók különféle hibákhoz vezethetnek, például szegmentálási hibákhoz, vagy hozzáférhetnek egy olyan memóriahelyhez, amelyre egyáltalán nincs szükség.
- Ha egy mutató nem megfelelő értéket ad meg, az memória sérülést okozhat.
- A memória szivárgásáért a mutató is felelős.
- A mutatók viszonylag lassabbak, mint a változóké.
- A programozóknak nagyon nehéz dolgozniuk a mutatókkal; ezért a programozó felelőssége, hogy gondosan manipuláljon egy mutatót.
Összegzés
- A mutató nem más, mint egy memóriahely, ahol az adatokat tárolják.
- Mutatóval lehet elérni a memória helyét.
- Különböző típusú mutatók léteznek, például null mutató, vad mutató, érvénytelen mutató és más típusú mutatók.
- A mutatókat tömbökkel és karakterláncokkal lehet használni az elemek hatékonyabb eléréséhez.
- Készíthetünk függvénymutatókat egy függvény dinamikus meghívására.
- A számtani műveletek elvégezhetők egy mutatón, amelyet úgy hívnak, hogy mutatószámtani.
- A mutatók olyan funkcióra is rámutathatnak, amely megkönnyíti a különböző függvények meghívását abban az esetben, ha mutató tömböt határoz meg.
- Ha különböző változó adattípussal kíván foglalkozni, használhatja a typecast void mutatót.