Publicitate

Indiferent dacă vă dați seama sau nu, marea majoritate a programelor pe care le-ați folosit folosesc indicatoarele într-un fel. Poate ați experimentat o NullPointerException la un moment dat. Ca programator, codul pe care îl scrii va folosi mai mult decât probabil indicatoarele, chiar dacă nu le-ai implementat singur.

Astăzi vă voi arăta cum funcționează indicatoarele, așa că poate doriți să consultați modul în care funcționează tablourile și listele Cum funcționează Schițele și Listele în PythonSchițele și listele sunt unele dintre cele mai utile structuri de date în programare - deși puține persoane le folosesc la potențialul lor maxim. Citeste mai mult pentru un primer de programare. Acest articol va fi mai mult bazat pe teorie decât de obicei, dar rămâne cu el, indicatoarele sunt foarte complexe!

Cod de compilare

Înainte de a săpa în pointeri, trebuie să înțelegeți cum este construit și executat codul - poate știți deja acest lucru. Această secțiune va avea afirmații destul de generale - lucruri care se aplică la majoritate de limbi, dar nu neapărat toate.

instagram viewer
pointeri

Să luăm lucrurile din nou la început. Fiecare computer folosește binare Ce este binarul? [Tehnologie explicată]Având în vedere că binarul este atât de fundamental pentru existența calculatoarelor, pare ciudat că nu am mai abordat subiectul până acum - așa că astăzi am crezut că voi oferi o scurtă privire de ansamblu a ceea ce binare ... Citeste mai mult , o serie de unități și zerouri care alcătuiesc tehnologia modernă așa cum o cunoaștem. Este extrem de dificil să codăm ceva în mod binar (fișierele ar fi foarte confuze), deoarece acestea sunt instrucțiunile brute necesare de către dvs. unități centrale de procesare sau CPU pentru a funcționa Ce este un procesor și ce face?Acronimele de calcul sunt confuze. Ce este oricum un procesor? Și am nevoie de un procesor quad sau dual-core? Ce zici de AMD sau Intel? Suntem aici pentru a ajuta la explicarea diferenței! Citeste mai mult . Aceasta este cunoscută sub numele de Codul mașinii.

Următorul pas de pe codul mașinii este Asamblare. Acesta este un format citit oarecum uman. Deși este încă complex de programat, este posibil. Ansamblul este format dintr-o serie de comenzi simple pentru a executa sarcini și este cunoscut sub numele de nivel scăzut limbaj de programare. Este posibil să scrie programe complexe, dar este dificil să exprimi concepte abstracte și necesită multă considerație.

Multe jocuri video și aplicații de înaltă performanță au o parte din logica scrisă în asamblare, deoarece unele creșteri reale ale vitezei pot fi găsite dacă știți ce faceți. Cu toate acestea, pentru marea majoritate a proiectelor de programare, nu este necesar să cunoașteți niciun ansamblu.

pointeri

Deci, dacă codul mașinii este prea dificil de scris, iar asamblarea este prea dificil de programat, cu ce scrieți codul? Iată unde nivel inalt limbile vin. Limbile la nivel înalt facilitează scrierea programelor. Puteți programa în ceva care seamănă cu limba dvs. maternă și este ușor de exprimat algoritmi complexi. Este posibil să fi auzit despre multe limbi la nivel înalt (și veți fi folosit cu siguranță un program scris în ele):

  • DE BAZĂ
  • C ++
  • foșnet

Aceste limbi sunt foarte vechi acum și multe au fost dezvoltate la începutul anilor '50! Aproape fiecare limbaj de programare modern este un limbaj la nivel înalt, inclusiv PHP și Python. Există mai multe limbi inventate în fiecare zi (deși probabil există suficiente acum), dar cum mai funcționează corect codul dvs. dacă calculatoarele necesită cod de mașină?

Iată locul în care apare compilarea. Un compilator este un program care transformă codul dvs. la nivel înalt într-o formă care poate fi executată. Acesta poate fi un alt limbaj la nivel înalt, dar este de obicei asamblarea. Unele limbi (cum ar fi Python sau Java) transformă codul într-o etapă intermediară numită bytecode. Acest lucru va trebui din nou să compileze la o dată ulterioară, care este de obicei făcută la cerere, cum ar fi atunci când se execută programul. Aceasta este cunoscută sub numele de la timp compilare și este destul de popular.

Gestionarea memoriei

După ce știți cum funcționează limbajele de programare, să ne uităm la gestionarea memoriei în limbaje la nivel înalt. Pentru aceste exemple, voi folosi pseudo cod - cod scris nu într-o limbă specifică, dar folosit pentru a arăta concepte, mai degrabă decât sintaxa exactă. Astăzi, aceasta se va asemăna mai ales cu C ++, deoarece acesta este cel mai bun limbaj la nivel înalt (după părerea mea).

Pentru această secțiune, vă va ajuta dacă înțelegeți cum funcționează memoria RAM Un ghid rapid și murdar pentru RAM: Ce trebuie să știțiMemoria RAM este o componentă crucială a fiecărui computer, dar poate fi confuză. Îl descompunem în termeni ușor de înțeles pe care îi veți înțelege. Citeste mai mult .

Majoritatea limbilor au variabile - containere care stochează unele date. Trebuie să definiți explicit tipul de date. Unele limbi tipizate dinamic, cum ar fi Python sau PHP, se ocupă de asta, dar trebuie să le facă.

Spuneți că aveți o variabilă:

int myNumber;

Acest cod declară o variabilă numită numărul meu, și îi oferă un tip de date întreg. Odată compilat, computerul interpretează această comandă ca:

„Găsiți o memorie goală și rezervați un spațiu suficient de mare pentru a stoca un număr întreg”

Odată executată această comandă, acel bit de memorie nu poate fi folosit de un alt program. Încă nu conține date, dar este rezervat pentru variabila dvs. Numărul meu.

Acum alocați o valoare variabilei dvs.:

myNumber = 10;

Pentru a finaliza această sarcină, computerul accesează locația rezervată a memoriei sale și modifică orice valoare este stocată acolo, la această nouă valoare.

Acum, totul este bine și bine, dar cum se fac locațiile de memorie nerezervate? Dacă programele ar rezerva toată memoria care le place, memoria RAM se va completa imediat - asta ar însemna o foarte sistem lent.

pointeri

Pentru a evita această problemă potențială, multe limbi implementează a colector de gunoi, folosit pentru a distruge variabilele (și, prin urmare, pentru a elibera locațiile de memorie rezervate) care au plecat fara scop.

Este posibil să vă întrebați care este scopul și de ce este atât de important. Scope definește limitele și durata de viață a variabilelor sau orice memorie utilizată de un program. O variabilă este „în afara domeniului de aplicare” atunci când nu mai poate fi accesată de niciun cod (adică atunci când colectorul de gunoi intră). Iată un exemplu:

function maths () {int firstNumber = 1; } int secundNumber = 2; print (firstNumber + secondNumber); // nu va funcționa

Acest exemplu nu va compila. Variabila firstNumber se află în interiorul matematica funcție, astfel încât acesta este scopul. Nu poate fi accesat din afara funcției în care a fost declarată. Acesta este un concept important de programareși înțelegerea este crucială pentru a lucra cu indicatoare.

Acest mod de manipulare a memoriei se numește grămadă. Este modul în care funcționează marea majoritate a programelor. Nu trebuie să înțelegeți indicatoarele pentru a-l utiliza și este destul de bine structurat. Dezavantajul stivei este viteza. Întrucât computerul trebuie să atribuie memorie, să țină evidența variabilelor și să ruleze colectarea gunoiului, există un mic capăt general. Acest lucru este în regulă pentru programe mai mici, dar ce zici de sarcini de înaltă performanță sau aplicații grele de date?

Introduceți: indicatoare.

pointeri

La suprafață, indicatoarele sună simplu. Se referă (arata spre) o locație în memorie. Este posibil să nu pară diferit de variabilele „obișnuite” de pe stivă, dar încredere în mine, există o diferență uriașă. Punctele sunt stocate pe morman. Acesta este opusul stivei - este mai puțin organizat, dar este mult mai rapid.

Să ne uităm la modul în care variabilele sunt alocate pe stivă:

număr intOne = 1; int numberTwo = numberOne;

Aceasta este sintaxa simplă; Variabila numarul doi conține numărul unu. Valoarea este copiată în timpul alocării din numărul unu variabil.

Dacă ai vrea să obții adresa de memorie pentru o variabilă, în loc de valoarea acesteia, trebuie să folosiți semnul ampersand (&). Aceasta se numește adresa din operator și este o parte esențială a setului de instrumente pentru pointer.

număr intOne = 1; int numberTwo = & numberOne;

Acum numarul doi variabil puncte într-o locație de memorie, în loc să obțineți numărul unu copiat în propria locație de memorie nouă. Dacă ar fi să ieșiți această variabilă, aceasta nu ar fi numărul unu (chiar dacă aceasta este stocată în locația memoriei). Ar ieși locația de memorie (probabil ceva de genul 2167, deși variază în funcție de sistem și de memoria RAM disponibilă). Pentru a accesa valoarea stocată într-un indicator, în loc de locația de memorie, trebuie să endiancu indicatorul. Aceasta accesează direct valoarea, care ar fi numărul unu în acest caz. Iată cum ai abandonat un indicator:

int numberTwo = * numberOne;

operator de dereferință este un asterisc (*).

Acesta poate fi un concept dificil de înțeles, așa că să trecem din nou peste el:

  • adresa din operatorul (&) stochează adresa de memorie.
  • operator de dereferință (*) accesează valoarea.

Sintaxa se schimbă ușor la declararea indicatoarelor:

int * myPointer;

Tipul de date al int aici se referă la tipul de date pointer puncte to, și nu tipul indicelui în sine.

Acum că știți care sunt indicatoarele, puteți face câteva trucuri cu adevărat îngrijite cu ei! Când memoria este utilizată, sistemul dvs. de operare pornește secvențial. Vă puteți gândi la RAM ca la găuri de porumbei. Multe găuri pentru a stoca ceva, doar unul poate fi folosit simultan. Diferența este că aceste găuri de porumbei sunt numerotate. Când alocați memorie, sistemul dvs. de operare pornește de la cel mai mic număr și funcționează. Nu va sări niciodată între numere aleatorii.

pointeri

Când lucrați cu indicatoare, dacă ați atribuit un tablou, puteți naviga cu ușurință la următorul element prin simplificarea incrementării indicelui.

Iată unde devine interesant. Când treci valori unei funcții (folosind variabile stocate pe stivă), aceste valori sunt copiate în funcția ta. Dacă acestea sunt variabile mari, acum programul le stochează de două ori. Când funcția dvs. este terminată, este posibil să aveți nevoie de o modalitate de a returna aceste valori. Funcțiile pot, în general, să întoarcă un singur lucru - deci, dacă doriți să returnați două, trei sau patru lucruri?

pointeri

Dacă treceți un pointer la funcția dvs., se adaugă numai adresa de memorie (care este minusculă). Acest lucru salvează multă muncă CPU-ului tău! Poate indicatorul tău indică un tablou imens de imagini - nu numai că funcția ta poate funcționa exact la fel datele stocate în aceeași locație de memorie, dar, odată finalizate, nu este nevoie să vă întoarceți orice.! Neat

Cu toate acestea, trebuie să fii foarte atent. Pointerii pot să iasă în afara domeniului de aplicare și să fie colectați de către colectorul de gunoi. Cu toate acestea, valorile stocate în memorie nu sunt colectate. Aceasta se numește scurgere de memorie. Nu mai puteți accesa datele (deoarece indicatoarele au fost distruse), dar se folosește încă memoria. Acesta este un motiv comun pentru multe programe să se prăbușească și poate să eșueze spectaculos dacă există o cantitate mare de date. De cele mai multe ori, sistemul dvs. de operare vă va ucide programul dacă aveți o scurgere mare (folosind mai multă RAM decât are sistemul), dar acest lucru nu este de dorit.

pointeri

Debugging indicatoare poate fi un coșmar, mai ales dacă lucrați cu cantități mari de date sau lucrați în bucle. Dezavantajele și dificultățile lor de înțeles merită cu adevărat compromisurile pe care le obții în performanță. Deși amintiți-vă, este posibil să nu fie întotdeauna necesare.

Asta este pentru azi. Sper că ai învățat ceva util despre un subiect complex. Desigur, nu am acoperit tot ce trebuie să știm - este un subiect foarte complex. Dacă sunteți interesat să aflați mai multe, vă recomand cu mare drag C ++ în 24 de ore.

Dacă acest lucru a fost un pic complex, aruncați o privire ghidul nostru către cele mai ușoare limbaje de programare 6 limbi de programare cel mai ușor de învățat pentru începătoriÎnvățarea la program înseamnă a găsi o limbă potrivită la fel de mult ca și despre procesul de edificare. Iată primele șase limbi de programare cele mai ușoare pentru începători. Citeste mai mult .

Ai învățat cum funcționează astăzi? Aveți sfaturi și trucuri pe care doriți să le partajați cu alți programatori? Salt la comentarii și împărtășește-ți gândurile de mai jos!

Joe este absolvent în informatică de la Universitatea din Lincoln, Marea Britanie. Este un dezvoltator de software profesionist, iar atunci când nu zboară drone sau scrie muzică, poate fi găsit adesea făcând fotografii sau producând videoclipuri.