Pointers
Aceasta este lecția care separă C de aproape orice alt limbaj. Pointerii. Sună înfricoșător, dar odată ce înțelegi ideea, sunt de fapt destul de eleganți
Un pointer este o variabilă care stochează adresa altei variabile. Gândește-te așa: fiecare variabilă trăiește undeva în memoria calculatorului, la o adresă specifică, un număr, exact ca un număr de cameră într-un imobil de birouri. Un pointer este o bucată de hârtie pe care ai notat acel număr de cameră
#include <stdio.h>
int main(void) {
int varsta = 25;
int *ptr = &varsta;
printf("Valoarea lui varsta: %d\n", varsta);
printf("Adresa lui varsta: %p\n", (void *)&varsta);
printf("Valoarea lui ptr: %p\n", (void *)ptr);
printf("Valoarea de la ptr: %d\n", *ptr);
return 0;
}
Doi operatori noi:
- &: operatorul adresa-lui. &varsta ne dă adresa la care este stocat
varstaîn memorie - *: operatorul de dereferențiere. *ptr ne dă valoarea de la adresa stocată în
ptr
Deci &varsta dă adresa, *ptr citește valoarea de la acea adresă. Sunt ca inverșii unul altuia
Declarația int *ptr spune "ptr este un pointer către un int". * de aici este parte din tip, nu operatorul de dereferențiere. La început e confuz, dar te obișnuiești
#include <stdio.h>
int main(void) {
int x = 10;
int *p = &x; // p pointeaza catre x
printf("%d\n", *p); // 10 - valoarea de la adresa pe care o tine p
return 0;
}
Putem și schimba valoarea prin pointer
#include <stdio.h>
int main(void) {
int x = 10;
int *p = &x;
*p = 42;
printf("%d\n", x); // 42 - x s-a schimbat!
return 0;
}
Hai să urmărim ce se întâmplă:
- x e creat cu valoarea 10, undeva în memorie
- p este un pointer care primește adresa lui x. Acum p "știe" unde locuiește x
- *p = 42 nu schimbă pointerul, ci merge la adresa din p și scrie 42 acolo
- cum p ținea adresa lui x, valoarea scrisă acolo este chiar x
Nu am atins x direct. Am trecut prin p, am urmat adresa, și am schimbat valoarea de acolo. Aceasta este puterea pointerilor
Pe primele sisteme UNIX de la Bell Labs, programatorii lucrau cu memoria exact la acest nivel: fiecare octet avea o adresă, iar un pointer greșit putea scrie peste memoria altui program. Din acest motiv, C te lasă foarte aproape de mașină, și de aceea trebuie să fii atent la ce pointer citești și ce pointer scrii
Tipuri diferite de pointeri pentru tipuri diferite:
#include <stdio.h>
int main(void) {
int a = 10;
int *ip = &a; // pointer catre int
double b = 3.14;
double *dp = &b; // pointer catre double
char c = 'A';
char *cp = &c; // pointer catre char
printf("%d %f %c\n", *ip, *dp, *cp);
return 0;
}
Tipul pointerului trebuie să se potrivească cu tipul către care pointează. Un int * poate pointa doar către un int. Așa știe C câți octeți să citească atunci când dereferențiezi
Misiune: Registrul de control al bandă magnetică
Ești operator de tură la centrul de calcul. Un cititor de bandă magnetică ți-a transmis o valoare inițială pentru registrul său de control, dar comanda nouă trebuie scrisă prin pointer: accesul direct la hardware nu e permis, doar prin adresă.
- Citește un int x din input
- Creează un pointer ptr care pointează către x
- Folosește pointerul ca să schimbi x în 42 (atribuie prin *ptr)
- Afișează atât x cât și *ptr, fiecare pe linia lui
Exemplu
Intrare
7
Ieșire
42
42
Exemplu
Intrare
100
Ieșire
42
42
Indiferent ce valoare are x la citire, după ce scrii prin pointer, x devine 42.