Pointer (programare computer)
AdaEdit
Ada este un limbaj puternic tastat în care sunt tastate toate pointerele și sunt permise numai conversii de tip sigur. Toate indicatoarele sunt inițial inițializate la null
, iar orice încercare de a accesa datele printr-un indicator null
face ca excepția să fie ridicată. Pointerii din Ada se numesc tipuri de acces. Ada 83 nu a permis aritmetica tipurilor de acces (deși mulți furnizori de compilatoare au furnizat-o ca o caracteristică non-standard), dar Ada 95 acceptă aritmetica „sigură” pe tipurile de acces prin pachetul System.Storage_Elements
.
BASICEdit
Câteva versiuni vechi ale BASIC pentru platforma Windows au avut suport pentru STRPTR () pentru a returna adresa unui șir și pentru VARPTR () pentru a returna adresa o variabilă. Visual Basic 5 a avut, de asemenea, suport pentru OBJPTR () pentru a returna adresa unei interfețe obiect și pentru ca un operator ADDRESSOF să returneze adresa unei funcții. Tipurile tuturor acestora sunt numere întregi, dar valorile lor sunt echivalente cu cele deținute de tipuri de pointer.
Dialectele mai noi ale BASIC, cum ar fi FreeBASIC sau BlitzMax, au totuși implementări complete de pointer. În FreeBASIC, aritmetica pe ANY
pointeri echivalent cu C „s void*
) sunt tratate ca și cum indicatorul ANY
ar avea o lățime de octeți. ANY
pointerele nu pot fi dereferențiate, ca în C. De asemenea, distribuirea între ANY
și orice alte tipuri nu va genera avertismente.
dim as integer f = 257dim as any ptr g = @fdim as integer ptr i = gassert(*i = 257)assert( (g + 4) = (@f + 1) )
Editarea C și C ++
În C și C ++ pointerele sunt variabile care stochează adrese și poate fi nul. Fiecare pointer are un tip la care arată, dar se poate arunca liber între tipurile de pointer (dar nu între un pointer funcțional și un pointer obiect). Un tip special de pointer numit „pointer gol” permite indicarea oricărui (non -funcție) obiect, dar este limitat de faptul că nu poate fi dereferențiat direct (va fi aruncat). Adresa în sine poate fi adesea manipulată direct prin aruncarea unui pointer către și de la un tip integral de dimensiune suficientă, deși rezultatele sunt definite de implementare și pot provoca într-adevăr un comportament nedefinit; în timp ce standardele C anterioare nu aveau un tip integral care era garantat să fie suficient de mare, C99 specifică numele uintptr_t
tipat definit în <stdint.h>
, dar o implementare nu trebuie să o furnizeze.
C ++ acceptă pe deplin indicatorii C și tipografia C. De asemenea, susține un nou grup de operatori de tipografiere pentru a ajuta la capturarea unor proiecte periculoase neintenționate la compilare. De la C ++ 11, biblioteca standard C ++ oferă și indicatori inteligenți (unique_ptr
, shared_ptr
și weak_ptr
) care poate fi folosit în unele situații ca o alternativă mai sigură la indicii C primitivi. C ++ acceptă, de asemenea, o altă formă de referință, destul de diferită de un pointer, numită pur și simplu un tip de referință sau referință.
Aritmetica indicatorului, adică capacitatea de a modifica adresa țintă a unui pointer cu operații aritmetice (ca precum și comparațiile de mărime), este restricționat de standardul de limbă să rămână în limitele unui singur obiect matrice (sau imediat după acesta) și va invoca altfel un comportament nedefinit. Adăugarea sau scăderea dintr-un pointer îl mută cu un multiplu de dimensiune De exemplu, adăugarea 1 la un pointer la valorile întregi de 4 octeți va crește adresa pointerului la 4 octeți cu 4. Acest lucru are ca efect creșterea indicatorului pentru a indica următorul element într-un contig matrice de numere întregi – care este adesea rezultatul dorit. Aritmetica indicatorului nu poate fi efectuată pe pointerele void
deoarece tipul de gol nu are dimensiune și, prin urmare, adresa ascuțită nu poate fi adăugată, deși gcc și alte compilatoare vor efectua aritmetică de octeți pe void*
ca o extensie non-standard, tratând-o ca și cum ar fi char *
.
Aritmetica indicatorului oferă programatorului un un singur mod de a face față diferitelor tipuri: adăugarea și scăderea numărului de elemente necesare în locul decalajului real în octeți. (Aritmetica indicatorului cu char *
folosește compensări de octeți, deoarece sizeof(char)
este 1 prin definiție.) În special, definiția C declară în mod explicit că sintaxa a
, care este n
– al doilea element al tabloului a
, este echivalent la *(a + n)
, care este conținutul elementului indicat de a + n
. Aceasta implică faptul că n
este echivalent cu a
și se poate scrie, de exemplu, a
sau 3
la fel de bine pentru a accesa al patrulea element al unui tablou a
.
Deși puternic, aritmetica indicatorului poate fi o sursă de erori de computer. Tinde să confunde programatorii începători, forțându-i în contexte diferite: o expresie poate fi una aritmetică obișnuită sau una aritmetică pointer și, uneori, este ușor să confundați unul cu altul. Ca răspuns la aceasta, multe limbaje moderne de calculator la nivel înalt (de exemplu Java) nu permit accesul direct la memorie folosind adrese. De asemenea, dialectul sigur Ciclonul abordează multe dintre problemele legate de indicatori. Consultați limbajul de programare C pentru mai multe discuții.
Pointerul void
sau void*
este acceptat în ANSI C și C ++ ca tip de pointer generic. Un pointer la void
poate stoca adresa oricărui obiect (nu funcție) și, în C, este implicit convertit la orice alt tip de pointer de obiect la atribuire, dar trebuie să fie exprimat în mod explicit dacă dereferențiat.K & RC a folosit char*
în scopul „indicatorului tip-agnostic” (înainte de ANSI C).
C ++ nu permite conversia implicită a void*
la alte tipuri de pointer, chiar și în atribuții. Aceasta a fost o decizie de proiectare pentru a evita proiectările nepăsătoare și chiar neintenționate, deși majoritatea compilatoarelor emit doar avertismente , nu erori, atunci când întâlniți alte distribuții.
În C ++, nu există void&
(referință la nul) care să completeze void*
(pointer to void), deoarece referințele se comportă ca aliasuri la variabilele pe care le indică și nu poate exista niciodată o variabilă al cărei tip să fie void
.
Prezentare generală a sintaxei declarației indicatorului Editați
Aceste declarații ale indicatorului c peste majoritatea variantelor de declarații de pointer. Desigur, este posibil să aveți indicatori triplu, dar principiile principale din spatele unui indicator triplu există deja într-un indicator dublu.
The () și au o prioritate mai mare decât *.
C # Edit
În limbajul de programare C #, indicatoarele sunt acceptate numai în anumite condiții: orice bloc de cod care include indicatori trebuie marcat cu cuvântul cheie unsafe
. Astfel de blocuri necesită, de obicei, permisiuni de securitate mai mari pentru a fi permise să ruleze. Sintaxa este în esență aceeași cu cea din C ++, iar adresa indicată poate fi fie gestionată, fie memorie neadministrată. Cu toate acestea, indicatoarele către memoria gestionată (orice indicator către un obiect gestionat) trebuie declarate folosind cuvântul cheie fixed
, care împiedică colectorul de gunoi să mute obiectul ascuțit ca parte a gestionării memoriei în timp ce pointerul este în domeniul de aplicare, menținând astfel adresa pointerului validă.
O excepție de la aceasta este utilizarea structurii IntPtr
, care este un echivalent gestionat în condiții de siguranță cu int*
și nu necesită cod nesigur. Acest tip este adesea returnat atunci când se utilizează metode din System.Runtime.InteropServices
, de exemplu:
Cadrul .NET include multe clase și metode în System
și System.Runtime.InteropServices
spații de nume (cum ar fi clasa Marshal
) care convertesc tipurile .NET (de exemplu, System.String
) către și de la mai multe tipuri și indicatori neadministrate (de exemplu, LPWSTR
sau void*
) pentru a permite comunicare cu cod neadministrat. Majoritatea acestor metode au aceleași cerințe de permisiune de securitate ca și codul neadministrat, deoarece pot afecta locurile arbitrare din memorie.
COBOLEdit
Limbajul de programare COBOL acceptă indicii pentru variabile. Obiectele de date primitive sau de grup (înregistrare) declarate în LINKAGE SECTION
ale unui program sunt inerent bazate pe pointer, unde singura memorie alocată în cadrul programului este spațiul pentru adresa elementului de date ( de obicei un singur cuvânt de memorie). În codul sursă al programului, aceste elemente de date sunt utilizate la fel ca orice altă variabilă WORKING-STORAGE
, dar conținutul lor este accesat în mod indirect indirect prin intermediul LINKAGE
.
Spațiul de memorie pentru fiecare obiect de date îndreptat este de obicei alocat dinamic folosind instrucțiuni CALL
externe sau prin construcții de limbaj extins încorporate, cum ar fi sau EXEC SQL
.
Versiunile extinse ale COBOL furnizează, de asemenea, variabile de pointer declarate cu USAGE
IS
POINTER
clauze. Valorile acestor variabile de pointer sunt stabilite și modificate folosind instrucțiunile SET
și SET
ADDRESS
.
Unele versiuni extinse ale COBOL furnizează, de asemenea, variabile PROCEDURE-POINTER
, care sunt capabile să stocheze adresele codului executabil.
PL / IEdit
Limbajul PL / I oferă suport complet pentru pointeri către toate tipurile de date (inclusiv pointeri către structuri), recursivitate, multitasking, gestionarea șirurilor și funcții extinse încorporate.PL / I a fost un salt înainte în comparație cu limbajele de programare ale timpului său. Indicatoarele PL / I sunt netipate și, prin urmare, nu este necesară distribuirea pentru dereferențierea sau atribuirea indicatorului. Sintaxa declarației pentru un pointer este DECLARE xxx POINTER;
, care declară un pointer numit „xxx”. Indicatoarele sunt utilizate cu variabile BASED
. O variabilă bazată poate fi declarată cu un localizator implicit (DECLARE xxx BASED(ppp);
sau fără (DECLARE xxx BASED;
), unde xxx este o variabilă bazată, care poate fi o variabilă de element, o structură sau o matrice, iar ppp este indicatorul implicit). O astfel de variabilă poate fi adresată fără o referință explicită a indicatorului (xxx=1;
sau poate fi adresată cu o referință explicită la localizatorul implicit (ppp) sau la orice alt indicator (qqq->xxx=1;
).
Aritmetica indicatorului nu face parte din standardul PL / I, dar mulți compilatori permit expresii de forma ptr = ptr±expression
. IBM PL / I are, de asemenea, funcția integrată PTRADD
pentru a efectua aritmetica. Aritmetica indicatorului este întotdeauna efectuată în octeți.
Compilatoarele IBM Enterprise PL / I au un nouă formă de pointer tastat numit HANDLE
.
DEdit
Limbajul de programare D este un derivat al C și C ++ care acceptă pe deplin C indicatori și tipografie C.
EiffelEdit
Limbajul orientat obiect Eiffel folosește valoare și semantică de referință fără aritmetică a indicatorului. gestionarea memoriei, int față cu software non-Eiffel și alte caracteristici.
FortranEdit
Fortran-90 a introdus o capacitate de indicare puternic tastată. Indicatorii Fortran conțin mai mult decât o simplă adresă de memorie. De asemenea, ele încapsulează limitele inferioare și superioare ale dimensiunilor matricei, pașilor (de exemplu, pentru a susține secțiuni de matrice arbitrare) și alte metadate. Un operator de asociere, =>
este utilizat pentru a asocia un POINTER
unei variabile care are un TARGET
atribut. Instrucțiunea Fortran-90 ALLOCATE
poate fi utilizată și pentru a asocia un pointer cu un bloc de memorie. De exemplu, următorul cod ar putea fi utilizat pentru a defini și a crea o structură de listă legată:
Fortran-2003 adaugă suport pentru indicatorii de procedură. De asemenea, ca parte a caracteristicii de interoperabilitate C, Fortran-2003 acceptă funcții intrinseci pentru convertirea indicatoarelor în stil C în indicatori Fortran și înapoi.
GoEdit
Go are indicatori. Sintaxa declarației sale este echivalentă cu cea a lui C, dar scrisă invers, terminând cu tipul. Spre deosebire de C, Go are colectarea gunoiului și nu permite aritmetica indicatorului. Tipurile de referință, ca în C ++, nu există. Unele tipuri încorporate, cum ar fi hărțile și canalele, sunt încadrate (adică la nivel intern sunt indicatori pentru structuri modificabile) și sunt inițializate utilizând funcția make
. Într-o abordare a sintaxei unificate între pointeri și non-pointeri, operatorul săgeată (->
) a fost abandonat: operatorul punct pe un pointer se referă la câmpul sau metoda obiectului dereferențiat . Totuși, acest lucru funcționează numai cu 1 nivel de indirectare.
JavaEdit
Spre deosebire de C, C ++ sau Pascal, nu există o reprezentare explicită a indicatorilor în Java. În schimb, structuri de date mai complexe, cum ar fi obiecte și tablouri, sunt implementate folosind referințe. Limbajul nu oferă niciun operator explicit de manipulare a indicatorului. Totuși, este posibil ca codul să încerce să dereferinteze o referință nulă (pointer nul), ceea ce duce la aruncarea unei excepții în timp de execuție. Spațiul ocupat de obiecte de memorie neriferențiate este recuperat automat prin colectarea gunoiului în timpul rulării.
Modula-2Edit
Pointerele sunt implementate la fel ca în Pascal, la fel ca și VAR
parametrii în apelurile de procedură. Modula-2 este chiar mai puternic tastat decât Pascal, cu mai puține moduri de a scăpa de sistemul de tip. Unele dintre variantele Modula-2 (cum ar fi Modula-3) includ colectarea gunoiului.
OberonEdit
La fel ca în cazul Modula-2, sunt disponibile indicii. Există încă mai puține moduri de a evita sistemul de tip, astfel încât Oberon și variantele sale sunt încă mai sigure în ceea ce privește indicatoarele decât Modula-2 sau variantele sale. La fel ca în Modula-3, colectarea gunoiului face parte din specificațiile de limbă.
PascalEdit
Spre deosebire de multe limbi care prezintă pointeri, standardul ISO Pascal permite doar pointerilor să facă referire la variabilele create dinamic care sunt anonime și nu le permite să facă referire la variabilele statice sau locale standard. Nu are aritmetica indicatorului. Pointerii trebuie, de asemenea, să aibă un tip asociat și un pointer către un tip nu este compatibil cu un pointer cu un alt tip (de exemplu, un pointer către un caracter nu este compatibil cu un pointer cu un întreg).Acest lucru ajută la eliminarea problemelor de securitate de tip inerente cu alte implementări ale indicatorului, în special cele utilizate pentru PL / I sau C. Îndepărtează, de asemenea, unele riscuri cauzate de indicii care atârnă, dar capacitatea de a renunța dinamic la spațiul de referință utilizând procedura standard (care are același efect ca funcția de bibliotecă free
găsită în C) înseamnă că riscul apariției indicatorilor nu a fost eliminat în totalitate.
Cu toate acestea, în unele implementări de compilatoare Pascal (sau derivate) comerciale și open source – cum ar fi Free Pascal, Turbo Pascal sau Object Pascal din Embarcadero Delphi – un pointer este permis să facă referire la variabilele statice sau locale standard și poate fi aruncat de la un tip de pointer la altul. Mai mult, aritmetica indicatorului este nelimitată: adăugarea sau scăderea dintr-un indicator îl mută cu acel număr de octeți în ambele direcții, dar folosind Inc
sau Dec
procedurile standard cu acesta mută indicatorul după mărimea tipului de date la care este declarat că indică. Un pointer netipat este, de asemenea, furnizat sub numele Pointer
, care este compatibil cu alte tipuri de pointer.