Osutajad C-s: Mis on osuti C-programmeerimises? Tüübid

Mis on pointer C-s?

. Pointer C-s on muutuja, mis salvestab teise muutuja aadressi. Kursorit saab kasutada ka muule osutifunktsioonile viitamiseks. Kursorit saab suurendada/vähendada, st näidata järgmisele/eelmisele mälukohale. Kursori eesmärk on säästa mäluruumi ja saavutada kiirem täitmisaeg.

Osutajate kasutamine C-s

Kui deklareerime muutuja v tüübiga int, salvestab v tegelikult väärtuse.

Osutajate kasutamine C-s

v on nüüd võrdne nulliga.

Kuid igal muutujal on peale väärtuse ka oma aadress (või lihtsamalt öeldes, kus see mälus asub). Aadressi saab hankida, kui panna muutuja nime ette ampersand (&).

Osutajate kasutamine C-s

Kui prindid muutuja aadressi ekraanile, näeb see välja täiesti juhusliku numbrina (pealegi võib see käivitusti erineda).

Proovime seda praktikas C-näites osutiga

Osutajate kasutamine C-s

Selle programmi väljund on -480613588.

Nüüd, mis on osuti? Väärtuse salvestamise asemel salvestab osuti muutuja aadressi.


Osuti muutuja

Int *y = &v;

MUUTUV PUNKT
A väärtus ladustatud a nimetatud salvestus-/mälu aadress A muutuja et osutab salvestus-/mäluaadress teine muutuja

Osuti deklareerimine

Nagu muutujad, viitavad sisse C programmeerimine peavad olema deklareeritud, enne kui neid saab teie programmis kasutada. Osutitele saab nimetada ükskõik mida, kui nad järgivad C nimetamisreegleid. Osuti deklaratsioonil on järgmine vorm.

data_type * pointer_variable_name;

Siin

  • andmetüüp on C muutujatüüpide kursori põhitüüp ja näitab muutuja tüüpi, millele osuti osutab.
  • Tärn (*: sama tärn, mida kasutatakse korrutamiseks), mis on kaudne operaator, deklareerib kursori.

Vaatame mõnda kehtivat osutideklaratsiooni selles C-osutajate õpetuses:

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 */

Käivitage kursor

Pärast kursori deklareerimist initsialiseerime selle nagu tavalised muutuja aadressiga muutujad. Kui C-programmeerimise viiteid initsialiseeritakse ja neid programmis kasutatakse, võivad tulemused olla ettearvamatud ja potentsiaalselt katastroofilised.

Muutuja aadressi saamiseks kasutame ampersandi (&) operaatorit, mis asetatakse muutuja nime ette, mille aadressi me vajame. Kursori lähtestamine toimub järgmise süntaksiga.

Osuti süntaks

 pointer = &variable;

Allpool on toodud lihtne programm osuti illustreerimiseks:

#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;
}

Väljund:

Address stored in a variable p is:60ff08
Value stored in a variable p is:10
Operator Tähendus
* Teenib 2 otstarvet

  1. Osuti deklaratsioon
  2. Tagastab viidatud muutuja väärtuse
& Teenib ainult 1 eesmärki

  • Tagastab muutuja aadressi

Osutite tüübid C-s

Järgmised on erinevad Osutite tüübid C-s:

Nullkursor

Saame luua nullkursori, määrates kursori deklareerimise ajal nullväärtuse. See meetod on kasulik, kui teil pole kursorile määratud aadressi. Nullkursor sisaldab alati väärtust 0.

Järgmine programm illustreerib nullkursori kasutamist:

#include <stdio.h>
int main()
{
	int *p = NULL; 	//null pointer
	printf(“The value inside variable p is:\n%x”,p);
	return 0;
}

Väljund:

The value inside variable p is:
0

Tühi osuti

In C programmeerimine, nimetatakse tühikukku ka üldiseks osutiks. Sellel pole standardset andmetüüpi. Tühjuse osuti luuakse märksõna void abil. Seda saab kasutada mis tahes muutuja aadressi salvestamiseks.

Järgmine programm illustreerib tühiku osuti kasutamist:

#include <stdio.h>
int main()
{
void *p = NULL; 	//void pointer
printf("The size of pointer is:%d\n",sizeof(p));
return 0;
}

Väljund:

The size of pointer is:4

Metsik osuti

Osutit peetakse metsikuks osutiks, kui seda ei initsialiseerita millekski. Seda tüüpi C-osutajad ei ole tõhusad, kuna need võivad osutada tundmatule mälukohale, mis võib meie programmis probleeme tekitada ja põhjustada programmi kokkujooksmist. Metsikute osutitega töötades tuleb alati olla ettevaatlik.

Järgmine programm illustreerib metsikkursori kasutamist:

#include <stdio.h>
int main()
{
int *p; 	//wild pointer
printf("\n%d",*p);
return 0;
}

Väljund:

timeout: the monitored command dumped core
sh: line 1: 95298 Segmentation fault      timeout 10s main

Muud tüüpi c-näidised on järgmised:

  • Rippuv osuti
  • Kompleksne osuti
  • Kursori lähedal
  • Kaugjuht
  • Suur osuti

Otsesed ja kaudsed pääsuosad

C-s on muutuvale sisule juurdepääsemiseks ja sellega manipuleerimiseks kaks samaväärset viisi

  • Otsene juurdepääs: kasutame otse muutuja nime
  • Kaudne juurdepääs: kasutame kursorit muutujale

Mõistame seda alloleva programmi abil

#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;}

Pärast programmi ilma vigadeta koostamist on tulemus:

Direct access, var = 1
Indirect access, var = 1

The address of var = 4202496
The address of var = 4202496

Indirect access, var = 48

Osuti aritmeetika C-s

Kursori toimingud on kokku võetud järgmisel joonisel

Osuti aritmeetika C-s
Pointer Operamine

Prioriteetne toiming (prioriteetsus)

C-osutitega töötades peame järgima järgmisi prioriteedireegleid:

  • Operaatoritel * ja & on sama prioriteet, mis unaartehtetel (eitus!, juurdekasv++, kahanemine–).
  • Samas avaldises hinnatakse unaartehteid *, &,!, ++, – paremalt vasakule.

Kui P osuti osutab muutujale X, siis * P saab kasutada kõikjal, kus X saab kirjutada.

Järgmised väljendid on samaväärsed:

int X =10
int *P = &Y;
For the above code, below expressions are true
Väljendus Ekvivalentne väljend
Y=*P+1

*P=*P+10

*P+=2

++*P

(*P)++

Y=X+1

X=X+10

X+=2

++X

X++

Viimasel juhul on vaja sulgusid: kuna unaartehteid * ja ++ hinnatakse paremalt vasakule, siis ilma sulgudeta suurendataks osutit P, mitte objekti, millele P osutab.

Allolev tabel näitab aritmeetikat ja põhitehteid, mida saab kasutada C osutitega tegelemisel

Operamine Selgitus
Ülesanne int *P1,*P2
P1=P2;
P1 ja P2 osutavad samale täisarvulisele muutujale
Suurendamine ja vähendamine Int *P1;
P1++;P1– ;
Nihke lisamine (konstantne) See võimaldab kursoril liigutada tabelis N elementi.
Kursorit suurendatakse või vähendatakse muutuja tüübi baitide arvu N korda.
P1+5;

C Osutajad ja massiivid näidetega

Traditsiooniliselt pääseme massiivi elementidele juurde selle indeksi abil, kuid selle meetodi saab osutite abil kõrvaldada. Osutitega on igale massiivi elemendile lihtne juurde pääseda.

#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;
}

Väljund:

1
2
3
4
5

Konkreetse numbri lisamine kursorile viib kursori asukoha liitmistoiminguga saadud väärtuseni. Oletame, et p on kursor, mis osutab hetkel mälukohale 0, kui sooritame järgmise liitmisoperatsiooni, p+1, siis käivitatakse see järgmiselt:

C Osutajad ja massiivid

Osuti lisamine/kasv

Kuna p osutab praegu pärast 0 lisamist asukohale 1, muutub väärtus 1-ks ja seega osutab kursor mälukohale 1.

C Osutajad ja stringid koos näidetega

String on täheobjektide massiiv, mis lõpeb nullmärgiga \ 0. Stringe saame manipuleerida osutite abil. See osuti C-näites selgitab seda jaotist

#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;
}

Väljund:

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
!

Teine viis stringide käsitlemiseks on näpunäidete massiiv, nagu järgmises programmis:

#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;}

Väljund:

Please remember these materials:
iron
copper
gold

Osutite eelised C-s

  • Osutajad on kasulikud mälukohtadele juurdepääsuks.
  • Osutajad pakuvad tõhusat viisi massiivistruktuuri elementidele juurdepääsuks.
  • Osujaid kasutatakse nii dünaamilise mälu eraldamiseks kui ka eraldamiseks.
  • Osujaid kasutatakse keerukate andmestruktuuride (nt lingitud loendi, graafiku, puu jne) moodustamiseks.

Osutite puudused C-s

  • Osutajate mõistmine on pisut keeruline.
  • Osutajad võivad põhjustada mitmesuguseid tõrkeid, nagu segmenteerimisvead, või pääseda juurde mälukohale, mida pole üldse vaja.
  • Kui osutile antakse vale väärtus, võib see põhjustada mälu rikkumist.
  • Osutajad vastutavad ka mälulekke eest.
  • Osutajad on suhteliselt aeglasemad kui muutujate omad.
  • Programmeerijatel on osutitega väga raske töötada; seetõttu on programmeerija kohustus kursorit hoolikalt manipuleerida.

kokkuvõte

  • Osuti pole midagi muud kui mälukoht, kuhu andmeid salvestatakse.
  • Mälu asukohale juurdepääsuks kasutatakse kursorit.
  • Osujaid on erinevat tüüpi, näiteks null-, metsik-, tühi- ja muud tüüpi osutid.
  • Osureid saab kasutada koos massiivi ja stringiga, et elementidele tõhusamalt juurde pääseda.
  • Funktsiooni dünaamiliseks kutsumiseks saame luua funktsiooninäitajaid.
  • Aritmeetilisi toiminguid saab teha osutiga, mida nimetatakse osuti aritmeetikaks.
  • Osutajad võivad osutada ka funktsioonile, mis muudab osutite massiivi määratlemise korral erinevate funktsioonide kutsumise lihtsaks.
  • Kui soovite käsitleda erinevat muutuja andmetüüpi, võite kasutada typecast tühisuse osutit.