Pointer ( în engleză pointer ) este o variabilă al cărei interval de valori constă din adrese de celule de memorie sau o valoare specială - adresa zero . Acesta din urmă este folosit pentru a indica faptul că pointerul nu se referă în prezent la niciuna dintre celulele valide. Indicatorii au fost inventați de Ekaterina Logvinovna Iuscenko în limbajul de programare a adreselor (1955), și nu de Harold Lawson în 1964, așa cum s-a crezut mult timp în străinătate [1] . În 1955, conceptele de adresare indirectă și de adresare a rangurilor superioare au fost introduse în Address Programming Language , care acoperă conceptul de pointer și domeniul său de aplicare în limbajele de programare moderne.
Indicatorii sunt utilizați în două domenii:
Limbajele de programare care prevăd tipul de pointeri conțin, de regulă, două operații de bază asupra acestora: atribuire și dereferire .
În 1955, limbajul de programare a adreselor (URSS) a introdus „operarea cu bară” (dereferențierea pointerului), care a fost implementată în hardware prin operarea F a procesorului în computerul Kiev (1955) și mai târziu în M-20 calculatoare , „ Dnepr ”, calculatoare din familia BESM (BESM-2, BESM-3, BESM-3M și BESM-4), familiile Minsk și Ural, precum și alte computere de fabricație sovietică. Utilizarea multiplă a dereferențării pointerului a fost, de asemenea, implementată în hardware-ul acestor computere prin operațiuni de actualizare a adreselor de grup pentru a accelera lucrul cu formate de tip arbore ( listele și alte tipuri de date abstracte sunt un caz special de formate asemănătoare arborelui).
Primul atribuie o anumită adresă indicatorului. Al doilea este folosit pentru a accesa valoarea din memorie indicată de indicator. Dereferențiarea poate fi explicită sau implicită; în majoritatea limbajelor de programare moderne, dereferențiarea are loc numai atunci când este specificat explicit[ ce? ] .
Un exemplu de lucru cu pointeri în limbajul C :
int n = 6 ; // Declararea unei variabile n de tip int și atribuirea acesteia la valoarea 6 int * pn = malloc ( sizeof ( int ) ); // Declararea pointerului pn și alocarea memoriei pentru acesta * pn = 5 ; // Dereference pointer și atribuiți valoarea 5 n = * pn ; // Atribuiți n valorii (5) indicată de pn free ( pn ); // Eliberează memoria ocupată pn = & n ; // Atribuiți pointerul pn la adresa variabilei n (pointerul va indica către n) n = 7 ; // *pn a devenit și el egal cu 7Operatorul unar &returnează adresa variabilei, iar operatorul *este folosit pentru a dereferi:
int sourceNum1 = 100 ; int sourceNum2 = 200 ; int * pNum1 = & sourceNum1 ; int * pNum2 = & sourceNum2 ; printf ( "Valoarea indicatorului de 1-%d, 2-%d \n " , * pNum1 , * pNum2 ); pNum1 = pNum2 ; printf ( "Valoarea indicatorului de 1-%d, 2-%d \n " , * pNum1 , * pNum2 );Dacă pointerul stochează adresa unui obiect, atunci se spune că pointerul se referă la acest obiect .
Limbile care prevăd utilizarea pointerilor pentru alocarea dinamică a memoriei trebuie să conțină un operator pentru alocarea explicită a variabilelor în memorie. În unele limbi, pe lângă acest operator, există și un operator pentru ștergerea explicită a variabilelor din memorie. Ambele operațiuni iau adesea forma unor rutine încorporate (funcțiile malloc și free în C, operatorii new și delete în C++ și așa mai departe). Când utilizați un indicator simplu, mai degrabă decât un indicator inteligent , ar trebui să ștergeți întotdeauna variabila din memorie în timp util pentru a evita scurgerile de memorie .
Un indicator de tip void vă permite să vă referiți la orice tip de date , inclusiv la o clasă . Această tehnologie stă la baza oricărui tip de bibliotecă Boost .
clasa A { câmp int ; }; AclA ; _ void * pA = ( gol * ) & clA ; // pointerul pA se referă la un obiect din clasa AExistă, de asemenea, pointeri către pointeri în programare. Ele stochează adrese de memorie unde există pointeri către memoria în care se află obiectul de date sau un alt pointer. Înlănțuirea unui pointer la un pointer care indică din nou către un pointer ne permite să introducem conceptul de dereferențiere multiplă de pointer (în limbajul de programare a adresei : „adresarea rangurilor mai înalte” ) și acțiunea corespunzătoare asupra pointerelor: Indirecție multiplă.
int x , * p , ** q ; x = 10 ; p = & x ; q = & p ; // pointer la pointer printf ( "%d" , ** q );Un pointer nul este un pointer care deține o valoare specială care indică faptul că variabila pointer dată nu se referă la (nu indică) niciun obiect. În limbajele de programare, este reprezentată printr-o constantă specială [4] :
Indicatorii sunt greu de gestionat. Este destul de ușor să scrieți o valoare greșită într-un indicator, ceea ce poate provoca o eroare greu de reprodus. De exemplu, ați schimbat din greșeală adresa unui pointer în memorie sau ați alocat incorect memoria pentru informații și aici vă poate aștepta o surpriză: o altă variabilă foarte importantă care este folosită doar în interiorul programului va fi suprascrisă. Înțelegerea exactă a erorii și reproducerea acesteia nu va fi ușor, iar eliminarea unor astfel de erori nu este întotdeauna o sarcină banală, uneori trebuie să rescrieți o parte semnificativă a programului [6] .
Pentru a rezolva unele dintre probleme, există metode de protecție și asigurare:
Un exemplu de eroare cu un pointer neinițializat:
/* programul este invalid. */ int main ( void ) { int x , * p ; // Memorie alocată pentru x, dar nu pentru *p x = 10 ; // Memoria se scrie 10 * p = x ; // 10 este scris într-o locație nedefinită din memorie, ceea ce poate duce la blocarea programului. returnează 0 ; }Într-un program atât de mic, problema poate trece neobservată. Dar, când programul crește, poate deveni brusc clar că variabila este scrisă între alte blocuri de date care sunt importante pentru program. Pentru a evita această situație, trebuie doar să inițializați indicatorul [6] .
Utilizarea incorectă a unui indicator:
#include <stdio.h> /* programul este nevalid */ int main ( void ) { int x , * p ; x = 10 ; p = x ; printf ( "%d" , * p ); returnează 0 ; }Apelul printf()nu afișează pe ecran valoarea lui х, care este 10. În schimb, o valoare necunoscută este scoasă - aceasta este rezultatul unei utilizări incorecte a operatorului de atribuire ( р = х;). Acest operator atribuie valoarea 10 indicatorului р, care ar trebui să conțină adresa, nu valoarea. Din fericire, eroarea din acest program este detectată de compilator - emite un avertisment despre o conversie neobișnuită a pointerului. Pentru a remedia eroarea, scrieți p = &х;[6] .
Utilizarea corectă a indicatoruluiO scurgere de memorie este un proces de scădere necontrolată a cantității de memorie cu acces aleatoriu liber (RAM) a unui computer asociat cu erori în rularea programelor care nu eliberează zonele de memorie inutile la timp sau cu erori în serviciile de control al memoriei sistemului.
char * pointer = NULL ; int i = 0 ; pentru ( i = 0 ; i < 10 ; i ++ ) { pointer = ( char * ) malloc ( 100 ); // Memoria se alocă de 10 ori } liber ( pointer ); // A este eliberat numai în ultimul cazAdresele de memorie atribuite pointerilor pot fi comparate. Comparațiile formei pNum1 < pNum2și pNum1 > pNum2sunt adesea folosite pentru a itera secvențial peste elementele unui tablou într-o buclă : pNum1corespunde poziției curente în memorie și corespunde pNum2 sfârșitului matricei. pNum1 == pNum2va returna true dacă ambii pointeri indică către aceeași locație de memorie.
Aritmetica adresei a apărut ca o continuare logică a ideii de pointeri moștenite din limbajele de asamblare: în acestea din urmă, este posibil să se indice un decalaj față de poziția curentă.
Operații tipice ale aritmeticii adresei:
int * p ; // Să spunem p puncte la adresa 200 p ++ ; // După creștere, indică 200 + sizeof(int) = 204 p -- ; // Acum indică înapoi la 200.În unele limbaje de programare, există clase (de obicei șabloane) care implementează interfața pointer cu o nouă funcționalitate care corectează unele dintre deficiențele menționate mai sus.
Creierul folosește grupuri de celule asemănătoare unui indicator pentru a îndeplini unele dintre sarcinile asociate cu memorarea informațiilor noi [7] .
Tipuri de date | |
---|---|
Ininterpretabil | |
Numeric | |
Text | |
Referinţă | |
Compozit | |
abstract |
|
Alte | |
subiecte asemănătoare |