Pointer (computerprogrammering)
AdaEdit
Ada is een sterk getypeerde taal waarin alle pointers worden getypt en alleen veilige typeconversies zijn toegestaan. Alle verwijzingen worden standaard geïnitialiseerd met null
, en elke poging om toegang te krijgen tot gegevens via een null
-aanwijzer veroorzaakt een uitzondering. Pointers in Ada worden toegangstypen genoemd. Ada 83 stond geen rekenkunde toe voor toegangstypen (hoewel veel compilerverkopers het als een niet-standaardfunctie leverden), maar Ada 95 ondersteunt “veilige” rekenkunde voor toegangstypen via het pakket System.Storage_Elements
.
BASICEdit
Verschillende oude versies van BASIC voor het Windows-platform hadden ondersteuning voor STRPTR () om het adres van een string te retourneren, en voor VARPTR () om het adres van een variabele. Visual Basic 5 had ook ondersteuning voor OBJPTR () om het adres van een objectinterface te retourneren, en voor een ADDRESSOF-operator om het adres van een functie te retourneren. De typen van dit zijn allemaal gehele getallen, maar hun waarden zijn gelijk aan die worden vastgehouden door aanwijzertypen.
Nieuwere dialecten van BASIC, zoals FreeBASIC of BlitzMax, hebben echter uitgebreide pointerimplementaties. In FreeBASIC, rekenkundige bewerkingen op ANY
pointers ( gelijk aan C “s void*
) worden behandeld alsof de ANY
-aanwijzer een bytebreedte was. ANY
pointers kunnen niet worden verwijderd, zoals in C. Ook zal casten tussen ANY
en andere type “s pointers geen waarschuwingen genereren.
dim as integer f = 257dim as any ptr g = @fdim as integer ptr i = gassert(*i = 257)assert( (g + 4) = (@f + 1) )
C en C ++ Bewerken
In C en C ++ zijn pointers variabelen die adressen opslaan en kan nul zijn. Elke aanwijzer heeft een type waarnaar het verwijst, maar men kan vrij casten tussen aanwijzertypen (maar niet tussen een functieaanwijzer en een objectaanwijzer). Een speciaal aanwijzertype genaamd de ‘lege aanwijzer’ maakt het mogelijk om naar alle (niet -function) object, maar wordt beperkt door het feit dat er niet rechtstreeks naar kan worden verwezen (het zal worden gegoten). Het adres zelf kan vaak direct worden gemanipuleerd door een pointer naar en van een integraal type van voldoende grootte te werpen, hoewel de resultaten implementatie-gedefinieerd zijn en inderdaad ongedefinieerd gedrag kunnen veroorzaken; terwijl eerdere C-standaarden geen integraal type hadden dat gegarandeerd groot genoeg was, specificeert C99 de uintptr_t
typedef-naam gedefinieerd in <stdint.h>
, maar een implementatie hoeft het niet te bieden.
C ++ ondersteunt C-pointers en C-typecasting volledig. Het ondersteunt ook een nieuwe groep typecasting-operators om enkele onbedoelde gevaarlijke casts tijdens het compileren te helpen opvangen. Sinds C ++ 11 biedt de standaard C ++ -bibliotheek ook slimme verwijzingen (unique_ptr
, shared_ptr
en weak_ptr
) die in sommige situaties kan worden gebruikt als een veiliger alternatief voor primitieve C-aanwijzers. C ++ ondersteunt ook een andere vorm van referentie, heel anders dan een pointer, gewoon een referentie of referentietype genoemd.
Pointer rekenkunde, dat wil zeggen, de mogelijkheid om het doeladres van een aanwijzer te wijzigen met rekenkundige bewerkingen (zoals evenals magnitude-vergelijkingen), wordt beperkt door de taalstandaard om binnen de grenzen van een enkel array-object (of net erna) te blijven, en zal anders ongedefinieerd gedrag oproepen. Door een aanwijzer op te tellen of af te trekken wordt deze verplaatst met een veelvoud van de grootte van het datatype. Als u bijvoorbeeld 1 aan een pointer toevoegt aan een geheel getal van 4 bytes, wordt het naar het byte-adres van de pointer verhoogd met 4. Dit heeft tot gevolg dat de pointer wordt verhoogd om naar het volgende element in een aaneengesloten array van gehele getallen – wat vaak het beoogde resultaat is. Pointer-rekenkunde kan niet worden uitgevoerd op void
-wijzers omdat het void-type geen grootte heeft, en daarom kan het puntige adres niet worden toegevoegd, hoewel gcc en andere compilers byte-berekeningen zullen uitvoeren op void*
als een niet-standaard extensie, die behandelt alsof het char *
is.
Pointer rekenkunde biedt de programmeur een enkele manier om met verschillende typen om te gaan: optellen en aftrekken van het aantal benodigde elementen in plaats van de daadwerkelijke offset in bytes. (Pointer rekenkunde met char *
pointers gebruikt byte-offsets, omdat sizeof(char)
per definitie 1 is.) In het bijzonder verklaart de C-definitie expliciet dat de syntaxis a
, het n
-e element van de array a
, is equivalent naar *(a + n)
, wat de inhoud is van het element waarnaar wordt verwezen door a + n
. Dit houdt in dat n
equivalent is aan a
, en dat men bijvoorbeeld a
kan schrijven of 3
even goed om toegang te krijgen tot het vierde element van een array a
.
Hoewel krachtig, kan aanwijzers rekenen een bron van computerfouten zijn. Het heeft de neiging om beginnende programmeurs in verwarring te brengen en hen in verschillende contexten te dwingen: een uitdrukking kan een gewone rekenkundige zijn of een rekenkundige aanwijzer, en soms is het gemakkelijk om de een voor de ander te verwarren. Als reactie hierop staan veel moderne computertalen op hoog niveau (bijvoorbeeld Java) geen directe toegang tot het geheugen toe met behulp van adressen. Ook lost het veilige C-dialect Cyclone veel van de problemen op met aanwijzingen. Zie programmeertaal C voor meer discussie.
De void
pointer, of void*
, wordt ondersteund in ANSI C en C ++ als een generiek aanwijzertype. Een pointer naar void
kan het adres van elk object (geen functie) opslaan en wordt in C impliciet geconverteerd naar een ander type objectpointer bij toewijzing, maar het moet expliciet worden gecast if dereferenced.K & RC gebruikte char*
voor het “type-agnostische pointer” -doel (vóór ANSI C).
C ++ staat de impliciete conversie van void*
naar andere aanwijzertypen niet toe, zelfs niet in toewijzingen. Dit was een ontwerpbeslissing om onzorgvuldige en zelfs onbedoelde casts te vermijden, hoewel de meeste compilers alleen waarschuwingen geven , geen fouten, wanneer u andere casts tegenkomt.
In C ++ is er geen void&
(verwijzing naar void) om void*
(pointer to void), omdat referenties zich gedragen als aliassen voor de variabelen waarnaar ze verwijzen, en er kan nooit een variabele zijn waarvan het type void
is.
Pointer declaraties syntax overzicht Bewerken
Deze pointer declaraties c over de meeste varianten van aanwijzerverklaringen. Het is natuurlijk mogelijk om triple pointers te hebben, maar de belangrijkste principes achter een triple pointer bestaan al in een dubbele pointer.
De () en hebben een hogere prioriteit dan *.
C # Edit
In de programmeertaal C # worden pointers alleen onder bepaalde voorwaarden ondersteund: elk codeblok inclusief pointers moet worden gemarkeerd met het unsafe
sleutelwoord. Dergelijke blokken vereisen meestal hogere beveiligingsmachtigingen om te mogen worden uitgevoerd. De syntaxis is in wezen hetzelfde als in C ++ en het aangegeven adres kan zowel beheerd als onbeheerd geheugen zijn. Verwijzingen naar beheerd geheugen (elke aanwijzer naar een beheerd object) moeten echter worden gedeclareerd met het sleutelwoord fixed
, dat voorkomt dat de garbage collector het puntige object verplaatst als onderdeel van geheugenbeheer terwijl de pointer valt binnen het bereik, waardoor het pointeradres geldig blijft.
Een uitzondering hierop is het gebruik van de IntPtr
-structuur, die een veilig beheerd equivalent is van int*
, en vereist geen onveilige code. Dit type wordt vaak geretourneerd bij het gebruik van methoden uit de System.Runtime.InteropServices
, bijvoorbeeld:
Het .NET-framework bevat veel klassen en methoden in de System
en System.Runtime.InteropServices
naamruimten (zoals de Marshal
klasse) die .NET-typen converteren (bijvoorbeeld System.String
) van en naar veel onbeheerde typen en verwijzingen (bijvoorbeeld LPWSTR
of void*
) om communicatie met onbeheerde code. De meeste van dergelijke methoden hebben dezelfde beveiligingstoestemmingvereisten als onbeheerde code, aangezien ze willekeurige plaatsen in het geheugen kunnen beïnvloeden.
COBOLEdit
De COBOL-programmeertaal ondersteunt verwijzingen naar variabelen. Primitieve of groep (record) data-objecten gedeclareerd binnen de LINKAGE SECTION
van een programma zijn inherent pointer-gebaseerd, waarbij het enige geheugen dat binnen het programma is toegewezen ruimte is voor het adres van het data-item ( typisch een enkel geheugenwoord). In de broncode van het programma worden deze gegevensitems net als elke andere WORKING-STORAGE
-variabele gebruikt, maar hun inhoud wordt impliciet indirect benaderd via hun LINKAGE
-aanwijzers .
Geheugenruimte voor elk aangewezen gegevensobject wordt doorgaans dynamisch toegewezen met behulp van externe CALL
-instructies of via ingesloten uitgebreide taalconstructies zoals EXEC CICS
of EXEC SQL
statements.
Uitgebreide versies van COBOL bieden ook pointervariabelen gedeclareerd met USAGE
IS
POINTER
clausules. De waarden van dergelijke pointervariabelen worden vastgesteld en gewijzigd met behulp van SET
en SET
ADDRESS
-instructies.
Sommige uitgebreide versies van COBOL bieden ook PROCEDURE-POINTER
variabelen, die de adressen van uitvoerbare code kunnen opslaan.
PL / IEdit
De PL / I-taal biedt volledige ondersteuning voor verwijzingen naar alle gegevenstypen (inclusief verwijzingen naar structuren), recursie, multitasking, stringverwerking en uitgebreide ingebouwde functies.PL / I was een behoorlijke sprong voorwaarts vergeleken met de programmeertalen van die tijd. PL / I-aanwijzers zijn zonder type, en daarom is er geen casting nodig voor het verwijderen van verwijzingen of toewijzing van de aanwijzer. De declaratiesyntaxis voor een pointer is DECLARE xxx POINTER;
, die een pointer declareert met de naam “xxx”. Aanwijzers worden gebruikt met BASED
variabelen. Een gebaseerde variabele kan worden gedeclareerd met een standaard locator (DECLARE xxx BASED(ppp);
of zonder (DECLARE xxx BASED;
), waarbij xxx een gebaseerde variabele is, die kan zijn een elementvariabele, een structuur of een array, en ppp is de standaard pointer). Zo’n variabele kan een adres zijn zonder een expliciete pointerreferentie (xxx=1;
, of kan worden geadresseerd met een expliciete verwijzing naar de standaard locator (ppp), of naar een andere pointer (qqq->xxx=1;
).
Pointer rekenkunde maakt geen deel uit van de PL / I-standaard, maar veel compilers staan uitdrukkingen toe van de vorm ptr = ptr±expression
. IBM PL / I heeft ook de ingebouwde functie PTRADD
om de rekenkundige bewerkingen uit te voeren. Aanwijzers worden altijd in bytes uitgevoerd.
IBM Enterprise PL / I-compilers hebben een nieuwe vorm van getypte pointer genaamd een HANDLE
.
DEdit
De D-programmeertaal is een afgeleide van C en C ++ die C volledig ondersteunt pointers en C-typecasting.
EiffelEdit
De objectgeoriënteerde taal van Eiffel gebruikt waarde- en referentiesemantiek zonder pointer-rekenkunde. Desalniettemin zijn er pointer-klassen beschikbaar. Ze bieden pointer-rekenkunde, typecasting geheugenbeheer, int erfacing met niet-Eiffel-software en andere functies.
FortranEdit
Fortran-90 introduceerde een sterk getypte pointer-mogelijkheid. Fortran-aanwijzers bevatten meer dan alleen een eenvoudig geheugenadres. Ze bevatten ook de onder- en bovengrenzen van array-afmetingen, stappen (bijvoorbeeld ter ondersteuning van willekeurige array-secties) en andere metagegevens. Een koppelingsoperator, =>
, wordt gebruikt om een POINTER
te koppelen aan een variabele met een TARGET
kenmerk. De Fortran-90 ALLOCATE
-instructie kan ook worden gebruikt om een pointer aan een geheugenblok te koppelen. De volgende code kan bijvoorbeeld worden gebruikt om een gekoppelde lijststructuur te definiëren en aan te maken:
Fortran-2003 voegt ondersteuning toe voor procedureaanwijzingen. Als onderdeel van de C Interoperability-functie ondersteunt Fortran-2003 ook intrinsieke functies voor het converteren van C-style pointers naar Fortran pointers en terug.
GoEdit
Go heeft pointers. De declaratiesyntaxis is gelijk aan die van C, maar dan andersom geschreven, eindigend met het type. In tegenstelling tot C heeft Go garbagecollection en staat rekenkunde met aanwijzers niet toe. Referentietypen, zoals in C ++, bestaan niet. Sommige ingebouwde typen, zoals kaarten en kanalen, zijn omkaderd (d.w.z. intern zijn het verwijzingen naar veranderlijke structuren), en worden geïnitialiseerd met de functie make
. In een benadering van uniforme syntaxis tussen aanwijzers en niet-aanwijzers, is de pijloperator (->
) verwijderd: de puntoperator op een aanwijzer verwijst naar het veld of de methode van het object waarvan de verwijzing is afgeleid . Dit werkt echter alleen met 1 indirectieniveau.
JavaEdit
In tegenstelling tot C, C ++ of Pascal, is er geen expliciete weergave van pointers in Java. In plaats daarvan worden complexere datastructuren zoals objecten en arrays geïmplementeerd met behulp van referenties. De taal biedt geen expliciete operators voor pointermanipulatie. Het is echter nog steeds mogelijk dat code probeert de verwijzing naar een null-referentie (null-pointer) ongedaan te maken, wat resulteert in een runtime-uitzondering die wordt gegenereerd. De ruimte die wordt ingenomen door niet-gerefereerde geheugenobjecten wordt automatisch hersteld door garbage collection tijdens runtime.
Modula-2Edit
Pointers worden op dezelfde manier geïmplementeerd als in Pascal, net als VAR
parameters in procedure-aanroepen. Modula-2 is zelfs sterker getypt dan Pascal, met minder manieren om aan het typesysteem te ontsnappen. Enkele van de varianten van Modula-2 (zoals Modula-3) omvatten garbage collection.
OberonEdit
Net als bij Modula-2 zijn er pointers beschikbaar. Er zijn nog steeds minder manieren om het typesysteem te omzeilen en dus zijn Oberon en zijn varianten nog veiliger met betrekking tot verwijzingen dan Modula-2 of zijn varianten. Net als bij Modula-3 is garbage collection een onderdeel van de taalspecificatie.
PascalEdit
In tegenstelling tot veel talen met pointers, staat standaard ISO Pascal pointers alleen toe om te verwijzen naar dynamisch gecreëerde variabelen die zijn anoniem en staan niet toe dat ze verwijzen naar standaard statische of lokale variabelen. Het heeft geen aanwijzer rekenkunde. Pointers moeten ook een geassocieerd type hebben en een pointer naar het ene type is niet compatibel met een pointer naar een ander type (bijv. Een pointer naar een teken is niet compatibel met een pointer naar een geheel getal).Dit helpt bij het elimineren van de typebeveiligingsproblemen die inherent zijn aan andere aanwijzerimplementaties, met name die welke worden gebruikt voor PL / I of C.Het verwijdert ook enkele risico’s die worden veroorzaakt door hangende aanwijzers, maar de mogelijkheid om de ruimte waarnaar wordt verwezen dynamisch los te laten door de dispose
standaardprocedure (die hetzelfde effect heeft als de free
bibliotheekfunctie gevonden in C) betekent dat het risico van hangende pointers niet volledig is geëlimineerd.
In sommige commerciële en open source Pascal (of afgeleide) compilerimplementaties – zoals Free Pascal, Turbo Pascal of de Object Pascal in Embarcadero Delphi – mag een pointer verwijzen naar standaard statische of lokale variabelen en kan cast van het ene aanwijzertype naar het andere. Bovendien is de rekenkunde van de aanwijzer onbeperkt: door een aanwijzer toe te voegen aan of af te trekken wordt deze met dat aantal bytes in beide richtingen verplaatst, maar met de Inc
of Dec
standaardprocedures ermee verplaatst de aanwijzer met de grootte van het gegevenstype waarnaar het wordt verklaard te wijzen. Een aanwijzer zonder type wordt ook geleverd onder de naam Pointer
, die compatibel is met andere typen aanwijzers.