Mainos

Tajuatko sen vai et, suurin osa käyttämistäsi ohjelmista hyödyntää osoittimia jollain tavalla. Ehkä olet kokenut a NullPointerException jossain vaiheessa. Ohjelmoijana kirjoittamasi koodi käyttää todennäköisemmin osoittimia, vaikka et olisi itse ottanut niitä käyttöön.

Tänään näytän sinulle, kuinka osoittimet toimivat, joten kannattaa ehkä tarkistaa miten taulukot ja luettelot toimivat Kuinka ryhmät ja luettelot toimivat PythonissaMatriisit ja luettelot ovat hyödyllisiä tietorakenteita ohjelmoinnissa - vaikka harvat ihmiset käyttävät niitä täysimääräisesti. Lue lisää ohjelmointialukkeelle. Tämä artikkeli tulee teoriapohjaisemmaksi kuin tavallisesti, mutta pysy siinä, osoittimet ovat erittäin monimutkaisia!

Kokoonpanokoodi

Ennen kuin kaivaudut osoittimiin, sinun on ymmärrettävä, kuinka koodi rakennetaan ja toteutetaan - ehkä tiedät tämän jo. Tässä osiossa on melko yleisiä lausumia - asioita, jotka koskevat suurin osa kielistä, mutta ei välttämättä kaikkia.

viitteitä

Otetaan asiat takaisin alkuun. Jokainen tietokone

käyttää binääristä Mikä on binaari? [Teknologia selitetty]Koska binaari on niin ehdottoman välttämätöntä tietokoneiden olemassaololle, vaikuttaa outolta, että emme ole koskaan käsitelleet aihetta aiemmin - joten tänään ajattelin antaa lyhyen yleiskuvan siitä, mitä binaareja ... Lue lisää , sarja niitä ja nollia, jotka muodostavat modernin tekniikan sellaisena kuin me sen tunnemme. On erittäin vaikea koodata mitään binaarista (tiedostot olisivat hyvin hämmentäviä), koska nämä ovat raakat ohjeet, joita tarvitset prosessori tai CPU toimimaan Mikä on CPU ja mitä se tekee?Lyhenteiden laskenta on hämmentävää. Mikä prosessori on joka tapauksessa? Tarvitsenko nelin- tai kaksoisydinsuorittimen? Entä AMD tai Intel? Olemme täällä auttaaksemme selittämään eron! Lue lisää . Tämä tunnetaan nimellä Konekoodi.

Seuraava askel konekoodista ylöspäin on kokoonpano. Tämä on hiukan ihmisen luettavissa oleva muoto. Vaikka ohjelmointi on edelleen monimutkaista, se on mahdollista. Kokoonpano koostuu sarjasta yksinkertaisia ​​komentoja tehtävien suorittamiseksi, ja se tunnetaan nimellä matala taso ohjelmointikieli. On mahdollista kirjoittaa monimutkaisia ​​ohjelmia, mutta abstrakteja käsitteitä on vaikea ilmaista, ja se vaatii paljon pohdintaa.

Monissa videopeleissä ja korkean suorituskyvyn sovelluksissa on osa logiikkaa kirjoitettu kokoonpanossa, koska todellinen nopeuden lisääntyminen löytyy, jos tiedät mitä teet. Suurimmassa osassa ohjelmointiprojekteja ei kuitenkaan tarvitse tuntea mitään kokoonpanoa.

viitteitä

Joten jos konekoodia on liian vaikea kirjoittaa ja kokoonpanoa on liian vaikea ohjelmoida, mistä kirjoitat koodin? Tässä on missä korkeatasoinen kielet tulevat sisään. Korkean tason kielet tekevät ohjelmien kirjoittamisen helpoksi. Voit ohjelmoida jotain, joka muistuttaa äidinkieltäsi, ja on helppo ilmaista monimutkaisia ​​algoritmeja. Olet ehkä kuullut monista korkean tason kielistä (ja olet varmasti käyttänyt niihin kirjoitettua ohjelmaa):

  • BASIC
  • C ++
  • lespata

Nämä kielet ovat nyt hyvin vanhoja, ja monet kehitettiin 1950-luvun alkupuolella! Lähes jokainen nykyaikainen ohjelmointikieli on korkean tason kieli, mukaan lukien PHP ja Python. Joka päivä keksitään enemmän kieliä (vaikka niitä on todennäköisesti nyt tarpeeksi), mutta kuinka koodisi toimii edelleen oikein, jos tietokoneet vaativat konekoodin?

Täältä löydät kokoamisen. Kääntäjä on ohjelma, joka muuntaa korkeatasoisen koodisi muotoon, joka voidaan suorittaa. Tämä voi olla toinen korkean tason kieli, mutta se on yleensä kokoonpano. Jotkut kielet (kuten Python tai Java) muuntaa koodisi nimeltä välivaiheeksi bytecode. Tämä on käännettävä uudelleen myöhemmin, mikä yleensä tehdään pyynnöstä, esimerkiksi kun ohjelma suoritetaan. Tämä tunnetaan nimellä juuri ajoissa kokoelma, ja se on melko suosittu.

Muistin hallinta

Nyt kun tiedät, kuinka ohjelmointikielet toimivat, tarkastellaan muistin hallintaa korkean tason kielillä. Käytän näitä esimerkkejä näennäiskoodi - koodi, jota ei kirjoiteta millään tietyllä kielellä, mutta jota käytetään käsitteiden esittämiseen tarkan syntaksin sijaan. Nykyään tämä muistuttaa enimmäkseen C ++: ta, joka on parhaiten korkean tason kieli (mielestäni).

Tässä osassa se auttaa, jos sinulla on ymmärrys miten RAM toimii Nopea ja likainen opas RAM-muistiin: mitä sinun täytyy tietääRAM-muisti on jokaisen tietokoneen tärkeä osa, mutta se voi olla hämmentävä. Hajotamme sen helposti ymmärrettävissä termeissä. Lue lisää .

Useimmilla kielillä on muuttujia - säilöt, jotka tallentavat joitain tietoja. Datatyyppi on määritettävä nimenomaisesti. Jotkut dynaamisesti kirjoitetut kielet, kuten Python tai PHP, käsittelevät tämän puolestasi, mutta heidän on silti tehtävä se.

Oletetaan, että sinulla on muuttuja:

int MyNumber;

Tämä koodi ilmoittaa muuttujan nimeltä numeroni, ja antaa sille tietotyypin kokonaisluku. Käännöksen jälkeen tietokone tulkitsee tämän komennon seuraavasti:

"Löydä tyhjä muisti ja varaa tarpeeksi iso tila kokonaisluvun tallentamiseksi"

Kun tämä komento on suoritettu, toinen ohjelma ei voi käyttää sitä muistia. Se ei sisällä vielä tietoja, mutta se on varattu myNumber-muuttujallesi.

Määritä nyt muuttujalle arvo:

mynumber = 10;

Suorittaaksesi tämän tehtävän tietokoneesi käyttää sen varattua muistipaikkaa ja muuttaa siihen tallennetun arvon uuteen arvoon.

Nyt tämä on kaikki hyvin, mutta miten muistipaikat säilyvät varaamattomina? Jos ohjelmat varaisivat kaiken haluamansa muistin, RAM täyttyisi heti - se tekisi a erittäin hidas järjestelmä.

viitteitä

Tämän mahdollisen ongelman välttämiseksi monet kielet toteuttavat a roskankerääjä, jota käytetään muuttujien tuhoamiseen (ja siksi vapautettujen muistipaikkojen vapauttamiseen), jotka ovat poistuneet soveltamisalan ulkopuolella.

Saatat ihmetellä, mikä on laajuus ja miksi se on niin tärkeä. Soveltamisala määrittelee muuttujien tai minkä tahansa ohjelman käyttämän muistin rajat ja eliniän. Muuttuja on ”laajuuden ulkopuolella”, kun siihen ei enää voida päästä millään koodilla (eli kun roskien kerääjä astuu sisään). Tässä on esimerkki:

funktio matematiikka () {int firstNumber = 1; } int secondNumber = 2; tulosta (ensimmäinen numero + toinen numero); // ei toimi

Tämä esimerkki ei koota. Muuttuja firstNumber on matematiikka toiminto, joten se on sen soveltamisala. Sitä ei voi käyttää sen toiminnon ulkopuolelta, jossa se on ilmoitettu. Tämä on tärkeä ohjelmointikonsepti, ja sen ymmärtäminen on välttämätöntä osoittimien kanssa työskentelyssä.

Tätä muistin käsittelytapaa kutsutaan pino. Se on tapa, jolla suurin osa ohjelmista toimii. Sinun ei tarvitse ymmärtää osoittimia käyttääksesi sitä, ja se on melko hyvin rakennettu. Pinohaitta on nopeus. Koska tietokoneen on määritettävä muisti, seurattava muuttujia ja suoritettava roskien keruu, siellä on pieni yläpinta. Tämä sopii pienemmille ohjelmille, mutta entä tehokkaat tehtävät tai tietoraskasovellukset?

Syötä: osoittimet.

viitteitä

Pinnalla osoittimet kuulostavat yksinkertaiselta. He viittaavat (osoittaa) sijainti muistissa. Tämä ei välttämättä näytä erilaiselta pino "säännöllisille" muuttujille, mutta luota minuun, siinä on valtava ero. Osoittimet tallennetaan pino. Tämä on vastakohta pinolle - se on vähemmän järjestetty, mutta on paljon nopeampaa.

Katsotaanpa miten muuttujat osoitetaan pinoon:

int lukuOne = 1; int numberTwo = numeroYksi;

Tämä on yksinkertainen syntaksi; Muuttuja numero kaksi sisältää numeron yksi. Arvon arvo kopioidaan koko tehtävän aikana numero yksi muuttuja.

Jos halusit saada muistiosoite muuttujasta, sen arvon sijasta, sinun on käytettävä ampersand-merkkiä (&). Tätä kutsutaan osoite operaattori, ja on olennainen osa osoittimen työkalupakkiisi.

int lukuOne = 1; int numberTwo = & numberOne;

Nyt numero kaksi muuttuja pistettä muistipaikkaan sen sijaan, että numero yksi kopioidaan sen omaan, uuteen muistipaikkaan. Jos tulostat tämän muuttujan, se ei olisi numero yksi (vaikka se on tallennettu muistipaikkaan). Se tuottaa muistin sijainnin (luultavasti jotain 2167, vaikka se vaihtelee järjestelmästä ja käytettävissä olevasta RAM: sta riippuen). Sinun on käytettävä osoittimeen tallennettua arvoa muistin sijaan dereference osoitin. Tämä käyttää arvoa suoraan, mikä olisi tässä tapauksessa numero yksi. Täältä saat ohjeet, joiden perusteella voit luopua osoittimesta:

int numberTwo = * numeroYksi;

dereferenssioperaattori on tähti (*).

Tämä voi olla vaikea ymmärtää käsitettä, joten katsotaan sen uudelleen:

  • osoite operaattori (&) tallentaa muistiosoitteen.
  • dereferenssioperaattori (*) käyttää arvoa.

Syntaksi muuttuu hieman osoittaessa osoittimia:

int * myPointer;

Tietojen tyyppi int tässä viitataan tietotyyppiin osoittimeen pistettä, eikä itse osoittimen tyyppi.

Nyt kun tiedät, mitkä osoittimet ovat, voit tehdä niistä todella siistejä temppuja! Kun muistia käytetään, käyttöjärjestelmäsi käynnistyy peräkkäin. Voit ajatella RAMia kyyhkynenreikinä. Paljon reikiä jonkin tallentamiseksi, vain yhtä voidaan käyttää kerralla. Ero tässä on, että nämä kyyhkysen reikät on kaikki numeroitu. Kun muistia määritetään, käyttöjärjestelmäsi alkaa pienimmästä luvusta ja toimii. Se ei koskaan hyppää ympäri satunnaislukuja.

viitteitä

Jos olet määrittänyt taulukon, osoittimien kanssa työskennellessäsi voit siirtyä helposti seuraavaan elementtiin yksinkertaisesti lisäämällä osoitinta.

Tässä on mielenkiintoista. Kun siirrät arvoja toiminnolle (pinoon tallennettujen muuttujien avulla), nämä arvot kopioidaan toimintoosi. Jos nämä ovat suuria muuttujia, tallennat ne nyt kahdesti. Kun toimintosi on valmis, saatat tarvita tapa palauttaa nämä arvot. Toiminnot voivat yleensä palauttaa vain yhden asian - niin entä jos haluat palauttaa kaksi, kolme tai neljä asiaa?

viitteitä

Jos siirrät osoittimen toimintoosi, vain muistiosoite kopioidaan (mikä on pieni). Tämä säästää prosessorillasi paljon työtä! Ehkä osoitin osoittaa valtavaan kuvanjoukkoon - toimintosi ei vain voi toimia täsmälleen samalla tavalla tietoja, jotka on tallennettu täsmälleen samaan muistipaikkaan, mutta kun se on valmis, sitä ei tarvitse palauttaa mitä vain. Siisti!

Sinun on kuitenkin oltava erittäin varovainen. Osoittimet voivat silti poiketa soveltamisalasta ja jätekeräilijä voi kerätä ne. Muistiin tallennettuja arvoja ei kuitenkaan kerätä. Tätä kutsutaan muistivuotoksi. Et voi enää käyttää tietoja (koska osoittimet on tuhottu), mutta se käyttää edelleen muistia. Tämä on yleinen syy monien ohjelmien kaatumiseen, ja se voi epäonnistua näyttävästi, jos tietoja on paljon. Suurimman osan ajasta käyttöjärjestelmä tappaa ohjelman, jos sinulla on suuri vuoto (käytät enemmän RAM-muistia kuin järjestelmässä on), mutta se ei ole toivottavaa.

viitteitä

Vianmääritysosoittimet voivat olla painajainen, etenkin jos työskentelet suurella tietomäärällä tai silmukoilla. Heidän haitat ja vaikeudet ymmärtää ovat todella kompromissien arvoisia, joita saat suorituskyvyssä. Vaikka muistat, niitä ei aina tarvita.

Se on se tänään. Toivon, että olet oppinut jotain hyödyllistä monimutkaisesta aiheesta. Emme tietenkään ole kata kaikkea tietävää - se on erittäin monimutkainen aihe. Jos olet kiinnostunut oppimaan lisää, suosittelen C ++ 24 tunnissa.

Jos tämä oli vähän monimutkaista, katso tätä opas helpoimpiin ohjelmointikieliin 6 helpointa ohjelmointikieltä aloittelijoilleOhjelmoinnissa on kyse oikean kielen löytämisestä yhtä paljon kuin editointiprosessissa. Tässä on kuusi parasta helpointa ohjelmointikieltä aloittelijoille. Lue lisää .

Oppitko kuinka osoittimet toimivat tänään? Onko sinulla vinkkejä ja temppuja, jotka haluat jakaa muiden ohjelmoijien kanssa? Hyppää kommentteihin ja jaa ajatuksesi alla!

Joe on valmistunut tietojenkäsittelytieteestä Lincolnin yliopistosta, Iso-Britannia. Hän on ammattimainen ohjelmistokehittäjä, ja kun hän ei lentä drooneja tai kirjoita musiikkia, hänet voidaan usein löytää ottamasta valokuvia tai tuottamaan videoita.