Mutatók C-ben: Mi a mutató a C programozásban? Típusok
Mi a Pointer C-ben?
A Mutató C-ben 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 pointer célja memóriaterület megtakarítása és gyorsabb végrehajtási idő elérése.
A mutatók használata C-ben
Ha deklarálunk egy int típusú v változót, akkor v ténylegesen tárol egy értéket.
v egyenlő most nullával.
Az értéken kívül azonban minden változónak megvan a címe (vagy egyszerűen fogalmazva: hol található a memóriában). A címet úgy lehet lekérni, hogy a változó neve elé egy „és” jelet (&) teszünk.
Ha egy változó címét kiírja a képernyőre, az teljesen véletlenszerű számnak fog kinézni (sőt, futásonként eltérő lehet).
Próbáljuk meg ezt a gyakorlatban a mutató segítségével a C példában
A program kimenete -480613588.
Nos, mi az a mutató? Érték tárolása helyett a mutató egy változó címét tárolja.
Mutatóváltozó
Int *y = &v;
VÁLTOZÓ | MUTATÓ |
---|---|
A érték tárolt a nevezett tároló/memória cím | A változó hogy mutat valahová a tárhely/memória címe másik változó |
Mutató deklarálása
Mint a változók, a mutatók C programozás deklarálniuk kell, mielőtt a programban felhasználhatók lesznek. A mutatókat bárminek el lehet nevezni, feltéve, hogy megfelelnek C elnevezési szabályainak. A mutató deklarációjának formája a következő.
data_type * pointer_variable_name;
Itt,
- adattípus a mutató C változótípusainak alaptípusa, és jelzi a változó típusát, amelyre a mutató mutat.
- A csillag (*: ugyanaz a csillag, mint a szorzásnál), amely indirekt operátor, mutatót deklarál.
Lássunk néhány érvényes mutatódeklarációt ebben a C pointers 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 */
Mutató inicializálása
A mutató deklarálása után úgy inicializáljuk, mint a szokásos változókat változó címmel. Ha a C programozás mutatóit inicializálás nélkül használják, és egy programban használják, az eredmények kiszámíthatatlanok és potenciálisan katasztrofálisak lehetnek.
Egy változó címének meghatározásához az „és” (&) operátort használjuk, amely egy olyan változó neve elé kerül, amelynek a 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ű program látható a mutató szemléltetésére:
#include <stdio.h> int main() { int a=10; //variable declaration int *p; //pointer variable declaration p=&a; //store address of variable a in pointer p printf("Address stored in a variable p is:%x\n",p); //accessing the address printf("Value stored in a variable p is:%d\n",*p); //accessing the value return 0; }
output:
Address stored in a variable p is:60ff08 Value stored in a variable p is:10
Operator | Jelentés |
---|---|
* | 2 célt szolgál
|
& | Csak 1 célt szolgál
|
A mutatók típusai C-ben
Az alábbiakban a különböző A mutatók típusai C-ben:
Null mutató
Létrehozhatunk nullmutatót, ha a mutató deklarációja során null értéket adunk hozzá. Ez a módszer akkor hasznos, ha nincs cím hozzárendelve a mutatóhoz. A nulla mutató mindig 0 értéket tartalmaz.
A következő program a null mutató használatát szemlélteti:
#include <stdio.h> int main() { int *p = NULL; //null pointer printf(“The value inside variable p is:\n%x”,p); return 0; }
output:
The value inside variable p is: 0
Üres mutató
In C programozás, az üres mutatót általános mutatónak is nevezik. Nincs szabványos adattípusa. A void mutató a void kulcsszó használatával jön létre. Bármely változó címének tárolására használható.
Az alábbi program az üres mutató használatát szemlélteti:
#include <stdio.h> int main() { void *p = NULL; //void pointer printf("The size of pointer is:%d\n",sizeof(p)); return 0; }
output:
The size of pointer is:4
Vad mutató
A mutatót vad mutatónak nevezik, ha nincs inicializálva semmire. Az ilyen típusú C-mutatók nem hatékonyak, mert egy ismeretlen memóriahelyre mutathatnak, ami problémákat okozhat a programunkban, és a program összeomlásához vezethet. Mindig legyen óvatos, amikor vad mutatókkal dolgozik.
A következő program a wild pointer használatát szemlélteti:
#include <stdio.h> int main() { int *p; //wild pointer printf("\n%d",*p); return 0; }
output:
timeout: the monitored command dumped core sh: line 1: 95298 Segmentation fault timeout 10s main
A 'c'-ben lévő egyéb mutatótípusok a következők:
- Lógó mutató
- Komplex mutató
- Mutató közelében
- Távoli mutató
- Hatalmas mutató
Közvetlen és közvetett hozzáférési mutatók
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 a változó nevét használjuk
- Közvetett hozzáférés: mutatót használunk a változóra
Értsük meg ezt az alábbi program segítségével
#include <stdio.h> /* 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 hibamentes fordítása után az eredmény:
Direct access, var = 1 Indirect access, var = 1 The address of var = 4202496 The address of var = 4202496 Indirect access, var = 48
Mutatós aritmetika C-ben
A mutató műveleteit a következő ábra foglalja össze
Elsőbbségi művelet (elsőbbség)
Amikor C-mutatókkal dolgozunk, be kell tartanunk a következő prioritási szabályokat:
- A * és & operátorok prioritása megegyezik az unáris operátorokkal (a tagadás!, az inkrementáció++, a csökkentés–).
- Ugyanebben a kifejezésben a *, &,!, ++, – unáris operátorok jobbról balra kerülnek kiértékelésre.
Ha egy P mutató egy X változóra mutat, akkor * P használható mindenhol, ahol X írható.
A következő kifejezések egyenértékűek:
int X =10 int *P = &Y; For the above code, below expressions are true
Kifejezés | Egyenértékű kifejezés |
---|---|
I=*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 unáris * és ++ operátorok jobbról balra kerülnek kiértékelésre, a zárójelek nélkül a P mutató növekszik, nem pedig az az objektum, amelyre P mutat.
Az alábbi táblázat bemutatja a C-mutatók kezelésekor használható számtani és alapműveleteket
OperaCIÓ | Magyarázat |
---|---|
Átruházás | int *P1,*P2 P1=P2; P1 és P2 ugyanarra az 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 a táblázatban. A mutató a változó típusának bájtjainak N-szeresével nő vagy csökken. P1+5; |
C Mutatók és tömbök példákkal
Hagyományosan a tömb elemeit annak indexével érjük el, de ez a módszer kiküszöbölhető mutatók használatával. A mutatók megkönnyítik az egyes tömbelemek elérését.
#include <stdio.h> int main() { int a[5]={1,2,3,4,5}; //array initialization int *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 elements p++; //incrementing to the next element, you can also write p=p+1 } return 0; }
output:
1 2 3 4 5
Ha egy adott számot hozzáad egy mutatóhoz, akkor a mutató helye az összeadási művelettel kapott értékre kerül. Tegyük fel, hogy p egy mutató, amely jelenleg a 0 memóriahelyre mutat, ha végrehajtjuk a következő összeadási műveletet, p+1, akkor a következő módon fog végrehajtani:
Mivel p jelenleg 0 hozzáadása után a 1 helyre mutat, az érték 1 lesz, így a mutató az 1-es memóriahelyre mutat.
C Mutatók és karakterláncok példákkal
A karakterlánc char objektumok tömbje, amely null karakterrel végződik '\ 0'. A karakterláncokat mutatók segítségével manipulálhatjuk. Ez a mutató a C példában magyarázza ezt a részt
#include <stdio.h> #include <string.h> 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 pointer for(int i=0;i<strlen(str);i++) { printf("%c\n",*p); p++; } return 0; }
output:
First character is:H Next character is:e Printing all the characters in a string H e l l o G u r u 9 9 !
A karakterláncok kezelésének másik módja a mutatók tömbje, mint a következő programban:
#include <stdio.h> int 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;}
output:
Please remember these materials: iron copper gold
A mutatók előnyei C-ben
- A mutatók hasznosak a memóriahelyek eléréséhez.
- A mutatók hatékony módot biztosítanak a tömbszerkezet elemeinek elérésére.
- A mutatókat a dinamikus memóriafoglaláshoz és a felszabadításhoz is használják.
- A mutatókat összetett adatszerkezetek, például linkelt lista, grafikon, fa stb. létrehozására használják.
A mutatók hátrányai C-ben
- A mutatók megértése kissé bonyolult.
- A mutatók különféle hibákhoz vezethetnek, például szegmentációs hibákhoz, vagy hozzáférhetnek egy olyan memóriahelyhez, amelyre egyáltalán nincs szükség.
- Ha helytelen értéket ad meg egy mutatónak, az memóriasérülést okozhat.
- A pointerek a memóriaszivárgásért is felelősek.
- A mutatók viszonylag lassabbak, mint a változóké.
- A programozók nagyon nehezen tudnak dolgozni a mutatókkal; ezért a programozó felelőssége a mutató gondos manipulálása.
Összegzésként
- A mutató nem más, mint egy memóriahely, ahol az adatok tárolódnak.
- A memóriahely eléréséhez egy mutatót használnak.
- Különféle típusú mutatók léteznek, például nullmutató, vad mutató, üres mutató és más típusú mutatók.
- A mutatók tömbökkel és karakterláncokkal együtt használhatók az elemek hatékonyabb eléréséhez.
- Létrehozhatunk függvénymutatókat a függvény dinamikus meghívásához.
- Az aritmetikai műveletek elvégezhetők egy mutatón, amelyet mutatóaritmetikának neveznek.
- A mutatók függvényre is mutathatnak, ami megkönnyíti a különböző függvények meghívását mutatók tömbjének meghatározása esetén.
- Ha különböző változó adattípusokat szeretne kezelni, használhat typecast void mutatót.