Advertentie

Of je het nu beseft of niet, de overgrote meerderheid van de programma's die je hebt gebruikt, maakt op de een of andere manier gebruik van verwijzingen. Misschien heb je een NullPointerException op een gegeven moment. Als programmeur gebruikt de code die u schrijft meer dan waarschijnlijk pointers, zelfs als u deze niet zelf heeft geïmplementeerd.

Vandaag laat ik je zien hoe pointers werken, dus misschien wil je eens kijken hoe arrays en lijsten werken Hoe arrays en lijsten werken in PythonArrays en lijsten zijn enkele van de nuttigste datastructuren bij het programmeren - hoewel weinig mensen ze ten volle benutten. Lees verder voor een programmeerprimer. Dit artikel zal meer op theorie gebaseerd zijn dan normaal, maar blijf erbij, pointers zijn erg complex!

Compilerende code

Voordat u in pointers gaat graven, moet u weten hoe code wordt gebouwd en uitgevoerd - misschien weet u dit al. Deze sectie bevat vrij algemene verklaringen - dingen die van toepassing zijn op de meerderheid talen, maar niet per se allemaal.

instagram viewer
Wijzers

Laten we teruggaan naar het begin. Elke computer gebruikt binair Wat is binair? [Technologie uitgelegd]Aangezien binair zo absoluut fundamenteel is voor het bestaan ​​van computers, lijkt het vreemd dat we het onderwerp nog nooit eerder hebben aangepakt - dus vandaag dacht ik dat ik een kort overzicht zou geven van wat binair is ... Lees verder , een reeks enen en nullen waaruit moderne technologie bestaat zoals wij die kennen. Het is buitengewoon moeilijk om iets in binaire code te coderen (de bestanden zouden erg verwarrend zijn), omdat dit de ruwe instructies zijn die uw centrale verwerkingseenheid of CPU om te functioneren Wat is een CPU en wat doet deze?Computerafkortingen zijn verwarrend. Wat is een CPU eigenlijk? En heb ik een quad- of dual-core processor nodig? Hoe zit het met AMD of Intel? We zijn hier om het verschil uit te leggen! Lees verder . Dit staat bekend als Machine code.

De volgende stap omhoog van machinecode is bijeenkomst. Dit is een enigszins door mensen leesbaar formaat. Hoewel het nog steeds moeilijk is om in te programmeren, is het mogelijk. Assembly bestaat uit een reeks eenvoudige opdrachten om taken uit te voeren en staat bekend als a laag niveau programmeertaal. Het is mogelijk om complexe programma's te schrijven, maar het is moeilijk om abstracte concepten uit te drukken en er is veel aandacht voor nodig.

Veel videogames en krachtige toepassingen hebben een deel van de logica die in de assemblage is geschreven, omdat er enkele echte snelheidsverhogingen zijn te vinden als je weet wat je doet. Voor de overgrote meerderheid van programmeerprojecten hoeft u helemaal geen vergadering te kennen.

Wijzers

Dus als machinecode te moeilijk is om te schrijven en assemblage te moeilijk is om te programmeren, waarmee schrijf je dan code? Hier is waar hoog niveau talen komen binnen. Talen op hoog niveau maken programma's gemakkelijk te schrijven. U kunt programmeren in iets dat lijkt op uw moedertaal en het is gemakkelijk om complexe algoritmen uit te drukken. Je hebt misschien al gehoord van veel talen op hoog niveau (en je zult zeker een programma hebben gebruikt dat erin is geschreven):

  • BASIS
  • C ++
  • Lispelen

Deze talen zijn nu erg oud en veel werden ontwikkeld in de vroege jaren 1950! Bijna elke moderne programmeertaal is een taal op hoog niveau, inclusief PHP en Python. Er worden elke dag meer talen uitgevonden (hoewel er nu waarschijnlijk genoeg zijn), maar hoe werkt uw code nog steeds correct als computers machinecode nodig hebben?

Hier komt compilatie binnen. Een compiler is een programma dat uw code op hoog niveau omzet in een vorm die kan worden uitgevoerd. Dit kan een andere taal op hoog niveau zijn, maar het is meestal assemblage. Sommige talen (zoals Python of Java) zetten uw code om in een tussenfase genaamd bytecode. Dit moet op een later tijdstip opnieuw worden gecompileerd, wat meestal op verzoek wordt gedaan, bijvoorbeeld wanneer het programma wordt uitgevoerd. Dit staat bekend als net op tijd compilatie, en het is behoorlijk populair.

Geheugen management

Nu u weet hoe programmeertalen werken, gaan we kijken naar geheugenbeheer in talen van hoog niveau. Voor deze voorbeelden gebruik ik pseudo-code - code die niet in een specifieke taal is geschreven, maar wordt gebruikt om concepten weer te geven in plaats van exacte syntaxis. Tegenwoordig zal dit grotendeels op C ++ lijken, omdat dat de beste taal op hoog niveau is (naar mijn mening).

Voor deze sectie zal het helpen als je er verstand van hebt hoe RAM werkt Een snelle en vuile handleiding voor RAM: wat u moet wetenRAM is een cruciaal onderdeel van elke computer, maar het kan verwarrend zijn. We splitsen het op in gemakkelijk te begrijpen termen die u zult begrijpen. Lees verder .

De meeste talen hebben variabelen: containers die bepaalde gegevens opslaan. U moet het datatype expliciet definiëren. Sommige dynamisch getypte talen zoals Python of PHP regelen dit voor je, maar ze moeten het nog steeds doen.

Stel dat je een variabele hebt:

int myNumber;

Deze code declareert een variabele genaamd mijn nummer, en geeft het een datatype van geheel getal. Eenmaal gecompileerd, interpreteert de computer deze opdracht als:

'Vind een leeg geheugen en reserveer een ruimte die groot genoeg is om een ​​geheel getal op te slaan'

Als deze opdracht eenmaal is uitgevoerd, kan dat stukje geheugen niet worden gebruikt door een ander programma. Het bevat nog geen gegevens, maar is gereserveerd voor uw myNumber-variabele.

Wijs nu een waarde toe aan uw variabele:

myNumber = 10;

Om deze taak te voltooien, krijgt uw computer toegang tot de gereserveerde geheugenlocatie en verandert de waarde die daar is opgeslagen in deze nieuwe waarde.

Dit is allemaal goed en wel, maar hoe worden geheugenlocaties onvoorwaardelijk? Als programma's al het gewenste geheugen zouden reserveren, zou het RAM-geheugen onmiddellijk vol raken - dat zou een heel traag systeem.

Wijzers

Om dit potentiële probleem te vermijden, implementeren veel talen een vuilnisman, gebruikt om variabelen te vernietigen (en dus de gereserveerde geheugenlocaties vrij te geven) die verdwenen zijn buiten bereik.

Je vraagt ​​je misschien af ​​wat de reikwijdte is en waarom het zo belangrijk is. Scope definieert de limieten en levensduur van variabelen of elk geheugen dat door een programma wordt gebruikt. Een variabele is 'out of scope' wanneer deze niet meer toegankelijk is door een code (dat is wanneer de garbage collector instapt). Hier is een voorbeeld:

functie wiskunde () {int firstNumber = 1; } int secondNumber = 2; print (firstNumber + secondNumber); // zal niet werken

Dit voorbeeld kan niet worden gecompileerd. De variabele firstNumber is binnen de wiskunde functie, dus dat is de reikwijdte. Het is niet toegankelijk van buiten de functie waarin het is gedeclareerd. Dit is een belangrijk programmeerconcept, en begrijpen dat het cruciaal is om met pointers te werken.

Deze manier van omgaan met geheugen wordt de genoemd stapel. Zo werkt de overgrote meerderheid van de programma's. Je hoeft geen aanwijzers te begrijpen om het te gebruiken en het is redelijk goed gestructureerd. Het nadeel van de stack is de snelheid. Omdat de computer geheugen moet toewijzen, variabelen moet bijhouden en de garbagecollection moet uitvoeren, is er een kleine overhead. Dit is prima voor kleinere programma's, maar hoe zit het met high-performance taken of data-zware applicaties?

Voer in: pointers.

Wijzers

Aan de oppervlakte klinken wijzers eenvoudig. Ze verwijzen (wijzen naar) een locatie in het geheugen. Dit lijkt misschien niet anders dan de "gewone" variabelen op de stapel, maar geloof me, er is een enorm verschil. Pointers zijn opgeslagen op de hoop. Dit is het tegenovergestelde van de stapel: deze is minder georganiseerd, maar is veel sneller.

Laten we eens kijken hoe variabelen worden toegewezen op de stapel:

int numberOne = 1; int numberTwo = numberOne;

Dit is een eenvoudige syntaxis; De variabele nummer twee bevat de nummer één. De waarde wordt tijdens de opdracht overgenomen van de nummer een variabel.

Als je de geheugenadres van een variabele, in plaats van de waarde ervan, moet u het teken en-teken (&) gebruiken. Dit heet de adres van operator en is een essentieel onderdeel van uw pointer toolkit.

int numberOne = 1; int numberTwo = & numberOne;

Nu de nummer twee variabel punten naar een geheugenlocatie, in plaats van de nummer één te kopiëren naar een eigen, nieuwe geheugenlocatie. Als u deze variabele zou uitvoeren, zou deze niet de nummer één zijn (ook al is die opgeslagen op de geheugenlocatie). Het zou zijn geheugenlocatie uitvoeren (waarschijnlijk zoiets als 2167, hoewel het varieert afhankelijk van het systeem en het beschikbare RAM). Om toegang te krijgen tot de waarde die is opgeslagen in een aanwijzer, moet u in plaats van de geheugenlocatie dereferentie de aanwijzer. Dit heeft rechtstreeks toegang tot de waarde, wat in dit geval de nummer één zou zijn. Hier leest u hoe u een aanwijzer herleid:

int numberTwo = * numberOne;

De dereferentie operator is een asterisk (*).

Dit kan een moeilijk concept zijn om te begrijpen, dus laten we het nog eens doornemen:

  • De adres van operator (&) slaat het geheugenadres op.
  • De dereferentie operator (*) heeft toegang tot de waarde.

De syntaxis verandert enigszins bij het declareren van pointers:

int * myPointer;

Het datatype van int hier verwijst naar het datatype de aanwijzer punten aan, en niet het type aanwijzer zelf.

Nu je weet wat pointers zijn, kun je er een paar hele leuke trucs mee doen! Wanneer geheugen wordt gebruikt, start uw besturingssysteem opeenvolgend. Je kunt RAM zien als duivengaten. Veel gaten om iets op te bergen, er kan er maar één tegelijk worden gebruikt. Het verschil is dat deze postvakjes allemaal genummerd zijn. Bij het toewijzen van geheugen begint uw besturingssysteem op het laagste nummer en werkt het op. Het zal nooit heen en weer springen tussen willekeurige getallen.

Wijzers

Als u met aanwijzers werkt, kunt u, als u een array hebt toegewezen, gemakkelijk naar het volgende element navigeren door uw aanwijzer eenvoudig te verhogen.

Hier wordt het interessant. Wanneer u waarden doorgeeft aan een functie (met behulp van variabelen die op de stapel zijn opgeslagen), worden deze waarden naar uw functie gekopieerd. Als dit grote variabelen zijn, slaat je programma ze nu twee keer op. Wanneer uw functie is voltooid, heeft u mogelijk een manier nodig om deze waarden te retourneren. Functies kunnen over het algemeen maar één ding retourneren, dus wat als u twee, drie of vier dingen wilt retourneren?

Wijzers

Als u een aanwijzer naar uw functie doorgeeft, wordt alleen het geheugenadres gekopieerd (wat klein is). Dit bespaart uw CPU veel werk! Misschien wijst uw aanwijzer op een enorme beeldreeks - niet alleen kan uw functie precies hetzelfde werken gegevens opgeslagen op exact dezelfde geheugenlocatie, maar als het eenmaal is gedaan, hoeft u niet terug te keren iets. Netjes!

Je moet wel heel voorzichtig zijn. Aanwijzers kunnen nog steeds buiten het bereik vallen en worden verzameld door de vuilnisman. De waarden die in het geheugen zijn opgeslagen, worden echter niet verzameld. Dit wordt een geheugenlek genoemd. Je hebt geen toegang meer tot de gegevens (omdat de aanwijzers zijn vernietigd), maar het gebruikt nog steeds geheugen. Dit is een veel voorkomende reden waarom veel programma's vastlopen en het kan spectaculair mislukken als er een grote hoeveelheid gegevens is. Meestal zal je besturingssysteem je programma doden als je een groot lek hebt (met meer RAM dan het systeem heeft), maar dat is niet wenselijk.

Wijzers

Pointers voor foutopsporing kunnen een nachtmerrie zijn, vooral als u met grote hoeveelheden gegevens werkt of in lussen werkt. Hun nadelen en moeilijk te begrijpen zijn echt de afwegingen waard die u wint in prestaties. Hoewel onthoud, zijn ze misschien niet altijd vereist.

Dat is het voor vandaag. Ik hoop dat je iets nuttigs hebt geleerd over een complex onderwerp. Natuurlijk hebben we niet alles besproken wat er te weten valt - het is een zeer complex onderwerp. Als je meer wilt weten, raad ik je ten zeerste aan C ++ in 24 uur.

Als dit een beetje ingewikkeld was, kijk dan eens naar onze gids voor de gemakkelijkste programmeertalen 6 eenvoudigste programmeertalen om te leren voor beginnersLeren programmeren gaat net zo goed over het vinden van de juiste taal als over het opbouwproces. Hier zijn de zes gemakkelijkste programmeertalen voor beginners. Lees verder .

Heb je geleerd hoe pointers vandaag werken? Heb je tips en trucs die je met andere programmeurs wilt delen? Spring in de reacties en deel uw mening hieronder!

Joe is afgestudeerd in computerwetenschappen aan de universiteit van Lincoln, VK. Hij is een professionele softwareontwikkelaar en als hij niet met drones vliegt of muziek schrijft, kan hij vaak foto's of video's maken.