logo

C++ osoittimet

Osoittimet ovat symbolisia esityksiä osoitteista. Niiden avulla ohjelmat voivat simuloida puhelukohtaisesti sekä luoda ja käsitellä dynaamisia tietorakenteita. Elementtien iterointi taulukoissa tai muissa tietorakenteissa on yksi osoittimien pääkäytöstä.

Käyttämäsi muuttujan osoite on määritetty osoitinmuuttujalle, joka osoittaa samaan tietotyyppiin (kuten int tai merkkijono).



np. missä

Syntaksi:

datatype *var_name; int *ptr; // ptr can point to an address which holds int data>
Kuinka osoitin toimii C++:ssa

Kuinka käyttää osoitinta?

  • Määritä osoitinmuuttuja
  • Muuttujan osoitteen antaminen osoittimelle käyttämällä unaarioperaattoria (&), joka palauttaa kyseisen muuttujan osoitteen.
  • Osoitteeseen tallennettuun arvoon pääsy käyttämällä unaarioperaattoria (*), joka palauttaa sen operandin määrittämässä osoitteessa sijaitsevan muuttujan arvon.

Syy, miksi yhdistämme tietotyypin osoittimeen, on että se tietää kuinka monelle tavulle tiedot on tallennettu . Kun suurennamme osoitinta, lisäämme osoitinta sen tietotyypin koolla, johon se osoittaa.

Osoittimet C++:ssaC++
// C++ program to illustrate Pointers #include  using namespace std; void geeks() {  int var = 20;  // declare pointer variable  int* ptr;  // note that data type of ptr and var must be same  ptr = &var;  // assign the address of a variable to a pointer  cout << 'Value at ptr = ' << ptr << '
';  cout << 'Value at var = ' << var << '
';  cout << 'Value at *ptr = ' << *ptr << '
'; } // Driver program int main()  {   geeks();   return 0; }>

Lähtö
Value at ptr = 0x7ffe454c08cc Value at var = 20 Value at *ptr = 20>

Viitteet ja osoittimet

On kolme tapaa välittää C++-argumentteja funktiolle:



  • Call-By-Value
  • Call-By-Reference osoitinargumentilla
  • Call-By-Reference ja viiteargumentti
C++
// C++ program to illustrate call-by-methods #include  using namespace std; // Pass-by-Value int square1(int n) {  // Address of n in square1() is not the same as n1 in  // main()  cout << 'address of n1 in square1(): ' << &n << '
';  // clone modified inside the function  n *= n;  return n; } // Pass-by-Reference with Pointer Arguments void square2(int* n) {  // Address of n in square2() is the same as n2 in main()  cout << 'address of n2 in square2(): ' << n << '
';  // Explicit de-referencing to get the value pointed-to  *n *= *n; } // Pass-by-Reference with Reference Arguments void square3(int& n) {  // Address of n in square3() is the same as n3 in main()  cout << 'address of n3 in square3(): ' << &n << '
';  // Implicit de-referencing (without '*')  n *= n; } void geeks() {  // Call-by-Value  int n1 = 8;  cout << 'address of n1 in main(): ' << &n1 << '
';  cout << 'Square of n1: ' << square1(n1) << '
';  cout << 'No change in n1: ' << n1 << '
';  // Call-by-Reference with Pointer Arguments  int n2 = 8;  cout << 'address of n2 in main(): ' << &n2 << '
';  square2(&n2);  cout << 'Square of n2: ' << n2 << '
';  cout << 'Change reflected in n2: ' << n2 << '
';  // Call-by-Reference with Reference Arguments  int n3 = 8;  cout << 'address of n3 in main(): ' << &n3 << '
';  square3(n3);  cout << 'Square of n3: ' << n3 << '
';  cout << 'Change reflected in n3: ' << n3 << '
'; } // Driver program int main() { geeks(); }>

Lähtö
address of n1 in main(): 0x7fffa7e2de64 address of n1 in square1(): 0x7fffa7e2de4c Square of n1: 64 No change in n1: 8 address of n2 in main(): 0x7fffa7e2de68 address of n2 in square2(): 0x7fffa7e2de68 Square of n2: 64 Change reflected in n2: 64 address of n3 in main(): 0x7fffa7e2de6c address of n3 in square3(): 0x7fffa7e2de6c Square of n3: 64 Change reflected in n3: 64>

C++:ssa argumentit välitetään oletusarvoisesti arvon mukaan, eivätkä kutsutussa funktiossa tehdyt muutokset heijastu välitettyyn muuttujaan. Muutokset tehdään kutsutun funktion tekemäksi klooniksi. Jos haluat muokata alkuperäistä kopiota suoraan (etenkin valtavan objektin tai taulukon ohittaessa) ja/tai välttää kloonauksen ylimääräiset kustannukset, käytämme ohitusviittausta. Pass-by-Reference viiteargumenttien kanssa ei vaadi kömpelöä syntaksia viittaamiseen ja viittauksen poistamiseen.

Taulukon nimi osoittimina

An joukko nimi sisältää taulukon ensimmäisen elementin osoitteen, joka toimii vakioosoittimena. Se tarkoittaa, että taulukon nimeen tallennettua osoitetta ei voi muuttaa. Esimerkiksi, jos meillä on taulukko nimeltä val, niin val ja &val[0] voidaan käyttää vaihtokelpoisesti.

C++
// C++ program to illustrate Array Name as Pointers #include  using namespace std; void geeks() {  // Declare an array  int val[3] = { 5, 10, 20 };  // declare pointer variable  int* ptr;  // Assign the address of val[0] to ptr  // We can use ptr=&val[0];(both are same)  ptr = val;  cout << 'Elements of the array are: ';  cout << ptr[0] << ' ' << ptr[1] << ' ' << ptr[2]; } // Driver program int main() { geeks(); }>

Lähtö
Elements of the array are: 5 10 20>
Tietojen esitys muistissa

Jos osoitin ptr lähetetään funktioon argumenttina, taulukkoon val voidaan päästä samalla tavalla. Osoitin vs Array



Osoitinlausekkeet ja osoitinaritmetiikka

Rajoitettu sarja aritmeettinen toiminnot voidaan suorittaa osoittimille, jotka ovat:

java abstrakti luokka
  • lisätty (++)
  • vähentynyt ( - )
  • osoittimeen voidaan lisätä kokonaisluku (+ tai +=)
  • kokonaisluku voidaan vähentää osoittimesta ( – tai -= )
  • kahden osoittimen ero (p1-p2)

( Huomautus: Osoitinaritmetiikka on merkityksetöntä, ellei sitä suoriteta taulukossa.)

C++
// C++ program to illustrate Pointer Arithmetic #include  using namespace std; void geeks() {  // Declare an array  int v[3] = { 10, 100, 200 };  // declare pointer variable  int* ptr;  // Assign the address of v[0] to ptr  ptr = v;  for (int i = 0; i < 3; i++) {  cout << 'Value at ptr = ' << ptr << '
';  cout << 'Value at *ptr = ' << *ptr << '
';  // Increment pointer ptr by 1  ptr++;  } } // Driver program int main() { geeks(); }>

Lähtö
Value at ptr = 0x7ffe5a2d8060 Value at *ptr = 10 Value at ptr = 0x7ffe5a2d8064 Value at *ptr = 100 Value at ptr = 0x7ffe5a2d8068 Value at *ptr = 200>
Tietojen esitys muistissa

Advanced Pointer Notation

Harkitse kaksiulotteisten numeeristen taulukoiden osoittimen merkintää. harkitse seuraavaa julistusta

int nums[2][3] = { { 16, 18, 20 }, { 25, 26, 27 } };>

Yleensä numerot[i ][ j ] vastaa *(*(numerot+i)+j)

Osoittimen merkintä C++:ssa

Osoittimet ja merkkijonokirjaimet

Merkkijonoliteraalit ovat taulukoita, jotka sisältävät nollapääteisiä merkkijonoja. Merkkijonoliteraalit ovat taulukoita, joiden tyyppi on merkki plus päättävä nollamerkki, ja jokainen elementti on tyyppiä const char (koska merkkijonon merkkejä ei voi muokata).

>

Tämä ilmoittaa taulukon, jossa on kirjaimellinen esitys geekille, ja sitten osoitin sen ensimmäiseen elementtiin määritetään ptr:lle. Jos kuvittelemme, että geek on tallennettu muistipaikkoihin, jotka alkavat osoitteesta 1800, voimme esittää edellisen ilmoituksen seuraavasti:

Osoittimet ja merkkijonokirjaimet

Koska osoittimet ja taulukot käyttäytyvät lausekkeissa samalla tavalla, ptr:llä voidaan käyttää merkkijonoliteraalin merkkejä. Esimerkiksi:

char ptr = 0; char x = *(ptr+3); char y = ptr[3];>

Tässä sekä x että y sisältävät k:n tallennettuna numeroon 1803 (1800+3).

Osoittimet osoittimiin

C++:ssa voimme luoda osoittimen osoittimeen, joka puolestaan ​​voi osoittaa dataan tai toiseen osoittimeen. Syntaksi yksinkertaisesti vaatii unaari-operaattorin (*) jokaiselle epäsuoran tasolle osoittimen ilmoittamisen aikana.

char a; char *b; char ** c; a = ’g’; b = &a; c = &b;>

Tässä b osoittaa merkkiä, joka tallentaa 'g' ja c osoittaa osoitinta b.

pythonin koko

Tyhjät osoittimet

Tämä on C++:ssa saatavilla oleva erityinen osoitin, joka edustaa tyypin puuttumista. Tyhjät osoittimet ovat osoittimia, jotka osoittavat arvoon, jolla ei ole tyyppiä (ja siten myös määrittelemätöntä pituutta ja määrittelemättömiä viittauksen purkamisominaisuuksia). Tämä tarkoittaa, että tyhjät osoittimet ovat erittäin joustavia, koska ne voivat osoittaa mihin tahansa tietotyyppiin. Tästä joustavuudesta on hyötyä. Näitä osoittimia ei voi suoraan poistaa. Ne on ensin muutettava joksikin muuksi osoitintyypiksi, joka osoittaa konkreettiseen tietotyyppiin, ennen kuin ne voidaan poistaa.

'muurarin kaava'
C++
// C++ program to illustrate Void Pointer #include  using namespace std; void increase(void* data, int ptrsize) {  if (ptrsize == sizeof(char)) {  char* ptrchar;  // Typecast data to a char pointer  ptrchar = (char*)data;  // Increase the char stored at *ptrchar by 1  (*ptrchar)++;  cout << '*data points to a char'  << '
';  }  else if (ptrsize == sizeof(int)) {  int* ptrint;  // Typecast data to a int pointer  ptrint = (int*)data;  // Increase the int stored at *ptrchar by 1  (*ptrint)++;  cout << '*data points to an int'  << '
';  } } void geek() {  // Declare a character  char c = 'x';  // Declare an integer  int i = 10;  // Call increase function using a char and int address  // respectively  increase(&c, sizeof(c));  cout << 'The new value of c is: ' << c << '
';  increase(&i, sizeof(i));  cout << 'The new value of i is: ' << i << '
'; } // Driver program int main() { geek(); }>

Lähtö
*data points to a char The new value of c is: y *data points to an int The new value of i is: 11>

Virheelliset osoittimet

Osoittimen tulee osoittaa kelvolliseen osoitteeseen, mutta ei välttämättä kelvollisiin elementteihin (kuten taulukoissa). Näitä kutsutaan virheellisiksi osoittimiksi. Alustamattomat osoittimet ovat myös virheellisiä.

int *ptr1; int arr[10]; int *ptr2 = arr+20;>

Tässä ptr1 on alustamaton, joten siitä tulee virheellinen osoitin ja ptr2 on arr-rajojen ulkopuolella, joten siitä tulee myös virheellinen osoitin. (Huomaa: virheelliset osoittimet eivät välttämättä aiheuta käännösvirheitä)

NULL-osoittimet

A nolla osoitin on osoitin, joka ei viittaa mihinkään, eikä vain virheellinen osoite. Seuraavassa on kaksi tapaa määrittää osoittimen arvoksi NULL;

int *ptr1 = 0; int *ptr2 = NULL;>

Osoittimien edut

  • Osoittimet vähentävät koodia ja parantavat suorituskykyä. Niitä käytetään merkkijonojen, puiden, taulukoiden, rakenteiden ja funktioiden hakemiseen.
  • Osoittimet antavat meille mahdollisuuden palauttaa useita arvoja funktioista.
  • Tämän lisäksi osoittimien avulla voimme käyttää muistipaikkaa tietokoneen muistissa.

Aiheeseen liittyvät artikkelit:

  • Läpinäkymätön osoitin
  • Lähellä, kaukana ja valtavat osoittimet

Tietokilpailut:

  • Osoittimen perusteet
  • Edistynyt osoitin