Osoittimet C:ssä: Mikä on osoitin C-ohjelmoinnissa? Tyypit

⚡ Älykäs yhteenveto

C-kielen osoittimet ovat muuttujia, jotka tallentavat toisen muuttujan muistiosoitteen. Ne mahdollistavat dynaamisen muistin allokoinnin, tehokkaan taulukoiden ja merkkijonojen käsittelyn sekä monimutkaiset tietorakenteet käyttämällä address-of- ja dereference-operaattoreita arvojen lukemiseen tai muokkaamiseen.

  • 📌 Määritelmä: Osoitin sisältää toisen muuttujan muistiosoitteen.
  • 🔧 Operatorit: &-operaattori palauttaa osoitteen; *-operaattori poistaa siihen viittaukset.
  • 🧷 ilmoitus: Kirjoita data_type *name ja alusta sitten muuttujan osoitteella.
  • 🏷️ tyypit: Null-, void- ja wild-osoittimet käyttäytyvät eri tavalla ja vaativat huolellisuutta.
  • Aritmeettinen: Osoittimen kasvattaminen siirtää sitä sen perustyypin koon verran.
  • 🤖 AI-apu: Tekoälytyökalut debuggaavat segmentointivirheitä ja merkitsevät roikkuvia osoittimia tarkastelun aikana.

Osoittimet C-kielellä

Mikä on osoitin C-kielessä?

A osoitin C-kielessä on muuttuja, joka tallentaa toisen muuttujan osoitteen. Osoitin voi myös viitata toiseen osoittimeen tai funktioon. Osoitinta voidaan kasvattaa tai vähentää osoittamaan seuraavaan tai edelliseen muistipaikkaan. Osoittimen tarkoituksena on säästää muistitilaa ja saavuttaa nopeampi suoritusaika.

Osoittimien käyttäminen C:ssä

Jos deklaroimme int-tyyppisen muuttujan v, v tallentaa arvon. Jokaisella muuttujalla on arvon lisäksi myös osoite, eli se sijainti muistissa. Osoitteen saa selville lisäämällä et-merkin (&) muuttujan nimen eteen. Jos tulostat muuttujan osoitteen, se näyttää satunnaisluvulta, joka voi vaihdella suoritusajasta toiseen.

Arvon tallentamisen sijaan osoitin tallentaa muuttujan osoitteen. Esimerkiksi:

int *y = &v;
MUUTTAVA OSOITIN
A arvo varastoitu a nimeltään tallennus-/muistiosoite. A muuttuja että pisteet tallennus-/muistiosoite toinen muuttuja.

Osoittimen ilmoittaminen

Kuten muuttujat, osoittimet sisään C ohjelmointi on ilmoitettava ennen kuin niitä voidaan käyttää. Osoitinilmoitus on seuraavan muotoinen:

data_type *pointer_variable_name;

Täällä tietotyyppi on osoittimen perustyyppi ja ilmaisee muuttujan tyypin, johon osoitin osoittaa. Tähti (*), sama symboli kuin kertolaskussa, on epäsuora operaattori, joka määrittää osoittimen. Joitakin kelvollisia osoittimen määrittelyjä ovat:

int    *ptr_thing;       /* pointer to an integer */
int    *ptr1, thing;     /* ptr1 points to an int; thing is an int */
double *ptr2;           /* pointer to a double */
float  *ptr3;           /* pointer to a float */
char   *ch1;            /* pointer to a character */

Osoittimen alustaminen

Osoittimen määrittämisen jälkeen alustamme sen muuttujaosoitteella. Jos osoitinta ei ole alustattu, tulokset voivat olla arvaamattomia ja mahdollisesti katastrofaalisia. Saadaksesi muuttujan osoitteen, käytä et-merkkiä (&) muuttujan nimen edessä:

pointer = &variable;

Yksinkertainen ohjelma, joka havainnollistaa osoittimen toimintaa, on annettu alla:

#include <stdio.h>
int main()
{
   int a = 10;     // variable declaration
   int *p;         // pointer variable declaration
   p = &a;        // store address of a in pointer p
   printf("Address stored in p is: %x\n", p);  // access the address
   printf("Value stored in p is: %d\n", *p);    // access the value
   return 0;
}

lähtö:

Address stored in p is: 60ff08
Value stored in p is: 10
OperaTor Merkitys
* Palvelee kahta tarkoitusta: määrittää osoittimen ja palauttaa viitatun muuttujan arvon (dereferenssi).
& Palvelee yhtä tarkoitusta: palauttaa muuttujan osoitteen.

Osoittimien tyypit C:ssä

Nollaosoitin

Luomme null-osoittimen antamalla sille arvon NULL määrittelyn aikana. Tämä on hyödyllistä, kun osoittimelle ei ole vielä annettu osoitetta. Null-osoitin sisältää aina arvon 0:

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

Tyhjä osoitin

Tyhjäosoitin, jota kutsutaan myös yleiseksi osoittimeksi, ei ole varustettu standarditietotyypillä. Se luodaan avainsanalla void ja se voi tallentaa minkä tahansa muuttujan osoitteen:

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

Villi osoitin

Osoitinta kutsutaan villiksi osoittimeksi, jos sitä ei ole alustettu mihinkään. Nämä osoittimet eivät ole tehokkaita, koska ne saattavat osoittaa tuntemattomaan muistipaikkaan, mikä voi aiheuttaa ongelmia ja kaataa ohjelman. Ole aina varovainen villien osoittimien kanssa:

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

Muita C-kielen osoittimien tyyppejä ovat roikkuva osoitin, kompleksiosoitin, lähiosoitin, kaukoosoitin ja valtava osoitin.

Suorat ja epäsuorat yhteysosoittimet

C-kielessä muuttujan sisällön käyttämiseen ja muokkaamiseen on kaksi samanarvoista tapaa. Suora käyttö käyttää muuttujan nimeä suoraan, kun taas epäsuora käyttö käyttää osoitinta muuttujaan:

#include <stdio.h>
int var = 1;        /* declare and initialize an int variable */
int *ptr;           /* declare a pointer to int */
int main(void)
{
   ptr = &var;       /* point ptr to var */
   printf("\nDirect access, var = %d", var);
   printf("\nIndirect access, var = %d", *ptr);
   *ptr = 48;        /* change var through the pointer */
   printf("\nIndirect access, var = %d", *ptr);
   return 0;
}

Osoittimen aritmetiikka C:ssä

Kun työskentelet osoittimien kanssa, noudata seuraavia prioriteettisääntöjä. Operaattoreilla * ja & on sama prioriteetti kuin unaarioperaattoreilla (negaatio !, lisäys ++, vähennys –). Samassa lausekkeessa unaarioperaattorit *, &, !, ++ ja — arvioidaan oikealta vasemmalle. Jos osoitin P osoittaa muuttujaan X, niin *P:tä voidaan käyttää kaikkialla, missä X voidaan kirjoittaa. Seuraavat lausekkeet ovat samanarvoisia:

Ilmaisu Vastaava ilmaisu
Y = *P + 1 Y = X + 1
*P = *P + 10 X = X + 10
*P + = 2 X + = 2
++*P ++X
(*P)++ X++

Viimeisessä tapauksessa sulkeet ovat pakollisia: koska unaarioperaattorit * ja ++ lasketaan oikealta vasemmalle, ilman sulkeita osoitin P kasvatettaisiin, ei sen osoittamaa objektia. Osoittimille käytettävissä olevat aritmeettiset operaatiot ovat sijoitus, lisäys ja vähennys sekä yhteen- tai alalasku.trackokonaislukuoffsetin asettaminen, joka siirtää osoitinta kyseisen määrän elementtejä (jokainen askel on yhtä suuri kuin perustyypin koko tavuina).

C-osoittimet ja taulukot esimerkkeineen

Perinteisesti taulukon alkioihin päästään indeksin avulla, mutta osoittimet tekevät tästäkin helppoa. Taulukon nimeen asetettu osoitin osoittaa ensimmäiseen alkioon:

#include <stdio.h>
int main()
{
   int a[5] = {1, 2, 3, 4, 5};   // array initialization
   int *p;                       // pointer declaration
   p = a;                       // p points to the first element; same as &a[0]
   for (int i = 0; i < 5; i++)
   {
      printf("%d\n", *p);            // print element
      p++;                      // move to the next element
   }
   return 0;
}

Luvun lisääminen osoittimeen siirtää sitä tietyn määrän alkioita eteenpäin. Jos p osoittaa muistipaikkaan 0, niin p + 1 siirtää osoittimen osoittamaan muistipaikkaan 1.

C Osoittimet ja merkkijonot esimerkein

Merkkijono on taulukko char-objekteja, jotka päättyvät null-merkkiin '\0'. Voimme käsitellä merkkijonoja osoittimien avulla:

#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);
   p = str;                     // reset the pointer
   for (int i = 0; i < strlen(str); i++)
   {
      printf("%c\n", *p);
      p++;
   }
   return 0;
}

Toinen tapa käsitellä merkkijonoja on osoittimien taulukon avulla:

#include <stdio.h>
int main()
{
   char *materials[] = {"iron", "copper", "gold"};
   for (int i = 0; i < 3; i++)
      printf("%s\n", materials[i]);
   return 0;
}

Osoittimien edut C:ssä

  • Osoittimet ovat hyödyllisiä muistipaikkojen suoraan käyttämiseen.
  • Ne tarjoavat tehokkaan tavan käyttää taulukon elementtejä.
  • Niitä käytetään dynaamiseen muistin allokointiin ja vapauttamiseen.
  • Niitä käytetään monimutkaisten tietorakenteiden, kuten linkitettyjen listojen, graafien ja puiden, muodostamiseen.

Osoittimien haitat C:ssä

  • Osoittimet ovat hieman monimutkaisia ​​ymmärtää.
  • Ne voivat aiheuttaa virheitä, kuten segmentointivirheitä tai pääsyä tahattomaan muistipaikkaan.
  • Osoittimelle annettu väärä arvo voi aiheuttaa muistin vioittumista.
  • Osoittimet ovat myös vastuussa muistivuotoista, jos muistia ei vapauteta.
  • Ohjelmoijan vastuulla on käsitellä osoitinta huolellisesti.

UKK

Roikkuva osoitin osoittaa vapautettuun tai mittausalueen ulkopuolella olevaan muistiin. Vältä se asettamalla osoittimen arvoon NULL heti free-kutsun jälkeen ja tarkistamalla, onko NULL-arvo ennen käyttöä.

NULL-osoittimen viittauksen poistaminen aiheuttaa segmentointivirheen ja kaataa ohjelman suorituksen aikana. Tarkista aina, että osoitin ei ole NULL, ennen kuin käytät *-operaattoria lukemiseen tai kirjoittamiseen.

Kaksoisosoitin, joka on määritelty muodossa int **pp, tallentaa toisen osoittimen osoitteen. Sitä käytetään dynaamisissa 2D-taulukoissa ja osoittimen argumentin muokkaamiseen funktion sisällä.

Osoitin tallentaa muistiosoitteen, ja osoitteet ovat saman levyisiä tietyllä alustalla, tyypillisesti 4 tavua 32-bittisessä ja 8 tavua 64-bittisessä, riippumatta siitä, mihin tyyppiin se osoittaa.

Funktiosoitin tallentaa funktion osoitteen, jotta sitä voidaan kutsua dynaamisesti. Sitä käytetään laajalti takaisinkutsuissa ja suorituksen aikana valittujen funktioiden taulukoiden rakentamisessa.

Funktiot, kuten malloc ja calloc, palauttavat osoittimen keolle suorituksen aikana varattuun muistiin. Muistia käytetään osoittimen kautta ja se vapautetaan free-komennolla vuotojen välttämiseksi.

Kyllä. Tekoälyavustajat lukevat segmentointivirheen ja sitä ympäröivän koodin, selittävät sitten todennäköisen syyn, kuten alustamattoman tai vapautuneen osoittimen, ja ehdottavat korjausta tarkistettavaksi.

Tekoälyllä toimivat analysaattorit yhdessä Valgrindin kaltaisten työkalujen kanssa merkitsevät muistia, jota ei koskaan vapauteta, ja osoittimia, joita käytetään vapauttamisen jälkeen. Ne automatisoivat tarkistuksen ja korostavat riskialttiita malleja ennen koodin lähettämistä.

Tiivistä tämä viesti seuraavasti: