En introduksjon til pekere for programmerere

En introduksjon til pekere for programmerere / programmering

Enten du skjønner det eller ikke, gjør det store flertallet av programmer du har brukt, bruk av pekere på en eller annen måte. Kanskje du har opplevd en NullPointerException på et tidspunkt. Som programmerer vil koden du skriver, mer enn sannsynlig bruke pekere, selv om du ikke har implementert dem selv.

I dag skal jeg vise deg hvordan poengene fungerer, så du kan kanskje sjekke hvordan arrays og lister fungerer. Hvordan Arrays and Lists Arbeid i Python. Hvordan Arrays and Lists Arter i Python Arrays og lister er noen av de mest nyttige datastrukturene i programmering - - Selv om få personer bruker dem til sitt fulle potensiale. Les mer for en programmeringsprimer. Denne artikkelen vil være mer teoribasert enn vanlig, men hold deg til det, pekere er svært komplekse!

Samlingskode

Før du graver inn pekere, må du forstå hvordan koden er bygget og utført - kanskje vet du dette allerede. Denne delen vil ha ganske generelle setninger - ting som gjelder for flertall av språk, men ikke nødvendigvis alle av dem.

La oss ta ting tilbake til starten. Hver datamaskin bruker binær Hva er binært? [Teknologi forklart] Hva er binært? [Teknologi forklart] Gitt at binær er så helt grunnleggende for eksistensen av datamaskiner, virker det merkelig at vi aldri har taklet emnet før - så i dag trodde jeg at jeg ville gi en kort oversikt over hvilket binært ... Les mer, en serie av dem og nuller som utgjør moderne teknologi som vi kjenner til det. Det er ekstremt vanskelig å kode noe i binær (filene vil være veldig forvirrende), da disse er de røde instruksjonene som trengs av din sentralenhet eller CPU for å fungere Hva er en CPU og hva gjør den? Hva er en CPU og hva gjør den? Computing akronymer er forvirrende. Hva er en CPU uansett? Og trenger jeg en quad- eller dual-core prosessor? Hva med AMD eller Intel? Vi er her for å hjelpe forklare forskjellen! Les mer . Dette er kjent som Maskinkode.

Det neste trinnet opp fra maskinskoden er montering. Dette er et noe menneskelig lesbart format. Selv om det fortsatt er komplekst å programmere inn, er det mulig. Montering består av en rekke enkle kommandoer for å utføre oppgaver, og er kjent som a lavt nivå programmeringsspråk. Det er mulig å skrive komplekse programmer, men det er vanskelig å uttrykke abstrakte begreper, og krever mye behandling.

Mange videospill og applikasjoner med høy ytelse har noe av logikken skrevet i montering, da noen reelle hastighetsøkninger kan bli funnet hvis du vet hva du gjør. Men for det store flertallet av programmeringsprosjekter trenger du ikke å vite noen samling i det hele tatt.

Så hvis maskinkode er for vanskelig å skrive, og montering er for vanskelig å programmere, hva skriver du kode med? Her er hvor høy level språk kommer inn. språk på høyt nivå gjør programmer enkle å skrive. Du kan programmere i noe som ligner morsmålet ditt, og det er lett å uttrykke komplekse algoritmer. Du har kanskje hørt om mange språk på høyt nivå (og du vil definitivt ha brukt et program skrevet i dem):

  • BASIC
  • C++
  • Lisp

Disse språkene er veldig gamle nå, og mange ble utviklet tidlig på 1950-tallet! Nesten alle moderne programmeringsspråk er et høyt nivå språk, inkludert PHP og Python. Det er flere språk som blir oppfunnet hver dag (selv om det nok er nok nå), men hvordan fungerer koden din fortsatt riktig hvis datamaskiner krever maskinkode?

Her er hvor kompilering kommer inn. En kompilator er et program som konverterer høynivåkoden til et skjema som kan utføres. Dette kan være et annet høyt språk, men det er vanligvis montering. Noen språk (som Python eller Java) konverterer koden til et mellomstadium som heter Bytecode. Dette må samles igjen på et senere tidspunkt, som vanligvis gjøres på forespørsel, for eksempel når programmet kjører. Dette er kjent som akkurat i tide kompilering, og det er ganske populært.

Minnehåndtering

Nå som du vet hvordan programmering av språk fungerer, la oss se på minnehåndtering på høynivå språk. For disse eksemplene bruker jeg pseudokode - kode skrevet ikke på noe bestemt språk, men pleide å vise konsepter i stedet for eksakt syntaks. I dag vil dette stort sett ligne på C ++, da det er det beste høynivåspråket (etter min mening).

For denne delen vil det hjelpe hvis du har en forståelse av hvordan RAM fungerer. En rask og skitten guide til RAM: Hva du trenger å vite En rask og skitten guide til RAM: Hva du trenger å vite RAM er en avgjørende komponent i hver datamaskin. , men det kan være forvirrende å forstå om du ikke er en teknologisk guru. I dette innlegget bryter vi det ned i enkle å forstå. Les mer .

De fleste språk har variabler - containere som lagrer noen data. Du må eksplisitt definere datatypen. Noen dynamisk skrivte språk som Python eller PHP håndterer dette for deg, men de må fortsatt gjøre det.

Si at du har en variabel:

int minNumber;

Denne koden erklærer en variabel som heter Nummeret mitt, og gir den en datatype av heltall. Når du er kompilert, tolker datamaskinen denne kommandoen som:

“Finn noe tomt minne, og reserver en plass som er stor nok til å lagre et heltall”

Når denne kommandoen er utført, kan den lille minnet ikke brukes av et annet program. Den inneholder ikke noen data ennå, men den er reservert for din myNumber-variabel.

Tilordne nå en verdi til variabelen din:

myNumber = 10;

For å fullføre denne oppgaven, får datamaskinen tilgang til det reserverte minnestedet, og endrer hvilken verdi som er lagret der, til denne nye verdien.

Nå er dette bra og bra, men hvordan får minnesteder seg ubehandlet? Hvis programmer reserverte alt minnet de vil, ville RAM fylle opp umiddelbart - det ville gjøre for en veldig sakte system.

For å unngå dette potensielle problemet, implementerer mange språk en søppelmann, brukes til å ødelegge variabler (og dermed slippe de reserverte minnesteder) som har gått utenfor omfanget.

Du lurer kanskje på hva omfanget er og hvorfor det er så viktig. Omfang definerer grenser og levetid for variabler eller noe minne som brukes av et program. En variabel er “utenfor omfanget” når det ikke lenger er tilgjengelig med noen kode (det er når søppelsamleren går inn). Her er et eksempel:

funksjon matematikk () int firstNumber = 1;  int secondNumber = 2; skriv ut (første nummer + andre nummer); // vil ikke fungere

Dette eksemplet vil ikke kompilere. Variabelen firstNumber er innenfor matte funksjon, så det er det omfanget. Den kan ikke nås utenom funksjonen der den er blitt erklært. Dette er et viktig programmeringskonsept, og forstå det er viktig å jobbe med pekere.

Denne måten å håndtere minne kalles stable. Det er måten de aller fleste programmer jobber på. Du trenger ikke å forstå poengene for å bruke det, og det er ganske godt strukturert. Ulempen med stabelen er hastigheten. Da datamaskinen må tilordne minne, holde styr på variabler, og kjøre søppelkolleksjonen, er det en liten overhead. Dette er greit for mindre programmer, men hva med høyytelsesoppgaver, eller datatunge applikasjoner?

Skriv inn: pekere.

pekere

På overflaten høres pekere enkelt. De refererer (peker på) et sted i minnet. Dette kan ikke virke annerledes enn “regelmessig” variabler på stakken, men stol på meg, det er en stor forskjell. Pekere lagres på heap. Dette er motsatt av stabelen - det er mindre organisert, men er mye raskere.

La oss se på hvordan variabler blir tildelt på stabelen:

int numberOne = 1; int numberTwo = numberOne;

Dette er enkel syntaks; Variabelen nummer to inneholder nummer én. Det er verdien kopieres på tvers under oppdraget fra nummer en variabel.

Hvis du ønsket å få minneadresse av en variabel, i stedet for verdien, må du bruke ampersand-tegnet (&). Dette kalles adresse på operatør, og er en viktig del av pekeren verktøyet.

int numberOne = 1; int numberTwo = & number One;

nummer to variabel punkter til en minneplass, i stedet for å få nummeret kopiert til sin egen, nye minneplass. Hvis du skulle skrive ut denne variabelen, ville det ikke være nummer ett (selv om det er lagret i minnestedet). Det ville sende det minneplassering (sannsynligvis noe som 2167, selv om det varierer avhengig av systemet og tilgjengelig RAM). For å få tilgang til verdien som er lagret i en peker, i stedet for minnestedet, må du dereference pekeren. Dette åpner verdien direkte, som vil være nummer ett i dette tilfellet. Slik viser du deg en pointer:

int numberTwo = * numberOne;

De dereference operatør er en stjerne (*).

Dette kan være et vanskelig konsept å forstå, så la oss gå over det igjen:

  • De adresse på operatør (&) lagrer minnesadressen.
  • De dereference operatør (*) åpner verdien.

Syntaxen endrer seg litt når de forklarer pekere:

int * myPointer;

Datatypen av int her refererer til datatypen pekeren punkter til, og ikke typen pekeren selv.

Nå som du vet hvilke poeng er, kan du gjøre noen veldig fine triks med dem! Når minnet blir brukt, starter operativsystemet sekvensielt. Du kan tenke på RAM som dukkehull. Mange hull til å lagre noe, bare en kan brukes samtidig. Forskjellen her er, disse dukkehullene er alle nummerert. Når du tilordner minne, starter operativsystemet ditt med det laveste nummeret og fungerer opp. Det vil aldri hoppe rundt mellom tilfeldige tall.

Når du jobber med pekere, hvis du har tilordnet en matrise, kan du enkelt navigere til neste element ved å enkelt øke pekeren.

Her blir det interessant. Når du overfører verdier til en funksjon (ved hjelp av variabler lagret på stakken), blir disse verdiene kopiert til din funksjon. Hvis disse er store variabler, lagrer du programmet nå to ganger. Når funksjonen er ferdig, kan det hende du trenger en måte å returnere disse verdiene på. Funksjoner kan generelt bare returnere en ting - så hva om du ville returnere to, tre eller fire ting?

Hvis du sender en peker til funksjonen din, blir bare minnet adressen kopiert (som er liten). Dette sparer din CPU mye arbeid! Kanskje pekeren peker på et stort bildeoppsett - ikke bare kan funksjonen din fungere på nøyaktig samme data som er lagret på nøyaktig samme minneplass, men når det er gjort, er det ikke nødvendig å returnere noe. Ryddig!

Du må være veldig forsiktig skjønt. Pekere kan fortsatt gå utenfor omfanget og samles inn av søppelkollektor. Verdiene som er lagret i minnet, blir imidlertid ikke samlet. Dette kalles et minnelekkasje. Du kan ikke lenger få tilgang til dataene (som pekerne er ødelagt), men det bruker fortsatt opp minne. Dette er en vanlig grunn til at mange programmer skal krasje, og det kan mislykkes spektakulært hvis det er en stor mengde data. Mesteparten av tiden vil operativsystemet drepe programmet hvis du har stor lekkasje (bruker mer RAM enn systemet har), men det er ikke ønskelig.

Feilsøkingspekere kan være et mareritt, spesielt hvis du jobber med store mengder data, eller jobber i looper. Deres ulemper og vanskeligheter med å forstå er virkelig verdt det avkastningen du får i ytelse. Selv om du husker det, kan de ikke alltid være påkrevd.

Det er det for i dag. Jeg håper du har lært noe nyttig om et komplekst emne. Selvfølgelig har vi ikke dekket alt som er å vite - det er et veldig komplekst emne. Hvis du er interessert i å lære mer, anbefaler jeg C ++ i 24 timer.

Hvis dette var litt komplisert, ta en titt på vår guide til de enkleste programmeringsspråkene. 6 Lettest programmeringssprog å lære for nybegynnere. 6 Letteste programmeringssprog å lære for nybegynnere Lære å programmere handler om å finne riktig språk like mye som det handler om oppbyggingsprosess. Her er de seks beste programmeringsspråket for nybegynnere. Les mer .

Lærte du hvordan pekere jobber i dag? Har du noen tips og triks du vil dele med andre programmerere? Hopp inn i kommentarene og del dine tanker nedenfor!

Utforsk mer om: Programmering.