Een inleiding tot pointers voor programmeurs

Een inleiding tot pointers voor programmeurs / Programming

Of je het nu beseft of niet, het overgrote deel van de programma's die je hebt gebruikt, maakt op de een of andere manier gebruik van pointers. Misschien heb je een ervaring gehad met NullPointerException op een gegeven moment. Als een programmeur, zal code die je schrijft meer dan waarschijnlijk pointers gebruiken, zelfs als je ze zelf niet hebt geïmplementeerd.

Vandaag zal ik je tonen hoe pointers werken, dus je zou willen weten hoe arrays en lijsten werken Hoe Arrays en lijsten werken in Python Hoe arrays en lijsten werken in Python Arrays en lijsten zijn enkele van de meest bruikbare datastructuren in programmeren - - hoewel maar weinig mensen ze volledig benutten. Lees meer voor een programmeerprimer. Dit artikel zal meer op theorie zijn gebaseerd dan gewoonlijk, maar blijf erbij, wijzers zijn erg complex!

Code compileren

Voordat je in pointers graaft, moet je begrijpen hoe code wordt gebouwd en uitgevoerd - misschien weet je dit al. Dit gedeelte bevat vrij algemene uitspraken - dingen die van toepassing zijn op de meerderheid van talen, maar niet noodzakelijk allemaal.

Laten we de dingen terug naar de start nemen. Elke computer gebruikt binair wat is binair? [Technology Explained] What Is Binary? [Technology Explained] Aangezien binary zo absoluut fundamenteel is voor het bestaan ​​van computers, lijkt het vreemd dat we het onderwerp nooit eerder hebben aangepakt - dus vandaag had ik gedacht dat ik een kort overzicht zou geven van wat binary ... Lees meer, een reeks enen en nullen die moderne technologie vormen zoals we die kennen. Het is buitengewoon moeilijk om iets in binaire code te coderen (de bestanden zouden erg verwarrend zijn), omdat dit de onbewerkte instructies zijn die je nodig hebt centrale verwerkingseenheid of CPU om te functioneren Wat is een CPU en wat doet het? Wat is een CPU en wat doet het? Computing acroniemen zijn verwarrend. Wat is een CPU eigenlijk? En heb ik een quad- of dual-coreprocessor nodig? Hoe zit het met AMD of Intel? We zijn hier om het verschil te helpen verklaren! Lees verder . Dit staat bekend als Machine code.

De volgende stap omhoog van machine-code is bijeenkomst. Dit is een enigszins menselijk leesbaar formaat. Hoewel het nog steeds moeilijk is om in te programmeren, is het mogelijk. De 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 dit vereist veel aandacht.

Veel videogames en high-performance applicaties hebben een deel van de logica die is geschreven in de assembly, omdat sommige echte snelheidsverhogingen kunnen worden gevonden als je weet wat je doet. Voor de meeste programmeringsprojecten hoeft u echter helemaal geen assembly te kennen.

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

  • BASIC
  • C++
  • Lispelen

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

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

Geheugen management

Nu je weet hoe programmeertalen werken, laten we kijken naar geheugenbeheer in talen van hoog niveau. Voor deze voorbeelden gebruik ik pseudo-code - geschreven in een andere taal, maar gebruikt om concepten te tonen in plaats van exacte syntaxis. Tegenwoordig zal dit vooral op C ++ lijken, want dat is de beste taal op hoog niveau (naar mijn mening).

Voor deze sectie helpt het als u begrijpt hoe RAM werkt. Een snelle en vuile gids voor RAM: wat u moet weten Een snelle en vuile gids voor RAM: wat u moet weten RAM is een cruciaal onderdeel van elke computer , maar het kan verwarrend zijn om te begrijpen of je geen technische goeroe bent. In dit bericht geven we het overzicht in eenvoudig te begrijpen termen. 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 verwerken dit voor u, 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:

“Zoek een leeg geheugen en reserveer een ruimte die groot genoeg is om een ​​geheel getal op te slaan”

Zodra dit commando is uitgevoerd, kan dat stukje geheugen niet door een ander programma worden gebruikt. Het bevat nog geen gegevens, maar het 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 wordt de waarde die daar is opgeslagen gewijzigd in deze nieuwe waarde.

Dit is allemaal goed en wel, maar hoe worden geheugenlocaties onvoorwaardelijk? Als programma's al het geheugen zouden reserveren dat ze leuk vinden, zou het RAM-geheugen onmiddellijk vollopen - dat zou een a opleveren heel langzaam systeem.

Om dit potentiële probleem te voorkomen, 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 “buiten bereik” wanneer het niet langer kan worden benaderd door een code (dat is wanneer de garbagecollector ingrijpt). Hier is een voorbeeld:

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

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

Deze manier van omgaan met geheugen wordt de stack. Het is de manier waarop de meeste programma's werken. U hoeft geen aanwijzingen te begrijpen om het te gebruiken, en het is redelijk goed gestructureerd. Het nadeel van de stapel 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 zware data-applicaties?

Enter: pointers.

pointers

Aan de oppervlakte klinken aanwijzers eenvoudig. Ze verwijzen naar (wijzen naar) een locatie in het geheugen. Dit lijkt misschien niet anders te zijn “regelmatig” variabelen op de stapel, maar geloof me, er is een enorm verschil. Pointers worden opgeslagen op de hoop. Dit is het tegenovergestelde van de stapel - het is minder georganiseerd, maar is veel sneller.

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

int numberOne = 1; int numberTwo = numberOne;

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

Als je de geheugen adres van een variabele, in plaats van zijn waarde, moet je het en-teken gebruiken (&). Dit wordt het adres van operator en is een essentieel onderdeel van uw pointertoolkit.

int numberOne = 1; int numberTwo = & numberOne;

Nu de nummer twee veranderlijk points naar een geheugenlocatie, in plaats van dat het nummer één gekopieerd wordt naar zijn eigen nieuwe geheugenlocatie. Als u deze variabele zou uitvoeren, zou dit niet het nummer één zijn (hoewel dat op de geheugenlocatie is opgeslagen). Het zou de geheugenlocatie uitvoeren (waarschijnlijk iets van 2167, hoewel dit afhankelijk is van het systeem en beschikbare RAM). Om toegang te krijgen tot de waarde die in een aanwijzer is opgeslagen, moet u in plaats van de geheugenlocatie dereference de aanwijzer. Hiermee krijgt u rechtstreeks toegang tot de waarde, die in dit geval de nummer één zou zijn. Hier leest u hoe u een aanwijzer derefferentieert:

int numberTwo = * numberOne;

De dereference operator is een asterisk (*).

Dit kan een moeilijk begrip zijn om te begrijpen, dus laten we er nog een keer over doen:

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

De syntax verandert enigszins bij het declareren van pointers:

int * myPointer;

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

Nu je weet wat pointers zijn, kun je een aantal heel leuke trucs met ze doen! Wanneer het geheugen wordt gebruikt, start uw besturingssysteem sequentieel. Je kunt RAM zien als duivengaten. Veel gaten om iets op te slaan, slechts één kan in één keer worden gebruikt. Het verschil is dat deze duivengaten allemaal zijn genummerd. Bij het toewijzen van geheugen begint uw besturingssysteem met het laagste nummer en werkt het op. Het zal nooit tussen willekeurige getallen springen.

Als u met pointers werkt en een array heeft toegewezen, kunt u eenvoudig naar het volgende element gaan door uw muisaanwijzer eenvoudigweg 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 gekopieerd naar uw functie. Als dit grote variabelen zijn, is uw programma nu twee keer opgeslagen. Wanneer uw functie is voltooid, hebt u mogelijk een manier nodig om deze waarden te retourneren. Functies kunnen over het algemeen maar één ding retourneren, dus wat als je twee, drie of vier dingen wilt retourneren??

Als u een aanwijzer naar uw functie doorgeeft, wordt alleen het geheugenadres gekopieerd (wat klein is). Dit bespaart je CPU veel werk! Misschien wijst uw wijzer naar een enorme afbeeldingsmatrix - niet alleen kan uw functie werken op exact dezelfde gegevens die op dezelfde exacte geheugenlocatie zijn opgeslagen, maar zodra deze is voltooid, hoeft u niets terug te sturen. Netjes!

Je moet echter wel heel voorzichtig zijn. Aanwijzers kunnen nog steeds buiten bereik raken 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 voor veel programma's om vast te lopen, en het kan spectaculair mislukken als er veel gegevens zijn. Meestal doodt je besturingssysteem je programma als je een groot lek hebt (met meer RAM dan het systeem heeft), maar dat is niet wenselijk.

Foutopsporingsaanwijzingen kunnen een nachtmerrie zijn, vooral als u met grote hoeveelheden gegevens werkt of in lussen werkt. Hun nadelen en moeilijkheid om te begrijpen zijn echt de moeite waard de trade offs die je wint aan prestaties. Alhoewel onthoud, ze zijn misschien niet altijd nodig.

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

Als dit een beetje ingewikkeld was, bekijk dan onze gids voor de gemakkelijkste programmeertalen 6 Eenvoudigste programmeertalen om te leren voor beginners 6 Eenvoudigste programmeertalen om te leren voor beginners Leren programmeren gaat over het vinden van de juiste taal, net zo goed als over de opbouwproces. Hier zijn de top zes van 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 commentaren en deel hieronder je gedachten!

Ontdek meer over: Programmeren.