Sunteți pe pagina 1din 31

Pointerii sunt utilizați în C, pentru o programarea mai ușoară, compactă, și pentru o

alocare dinamică a memoriei.


În C fiecare variabilă are alocat un spațiu de memorie, iar fiecare locație de memorie
are adresa sa bine definită, care poate fi accesată folosind operatorul ampersand &.
Operatorii specifici:
&x - returnează adresa (locația) unei variabile x
*x - returnează valoarea (conținutul) adresei variabilei x
1.
#include <stdio.h>

int main ()
{
int x;
char sir[10];
printf("Adresa variabilei x: %x\n", &x);
printf("Adresa variabilei sir: %x\n", &sir);
return 0;
}
2.
#include <stdio.h>

int main ()
{
int *p, c=5;
printf("Valoarea lui c este %d,
\niar adresa accesata de p este %x\n", c, p = &c);
return 0;
}
3.
#include <stdio.h>

int main ()
{
int x=1, y=2, z;
int *ip;
printf("Valoarea lui x=%d preluata de la adresa *ip=&x=%x\n", x, ip=&x);
printf("Acum *ip are valoarea lui x, ip=%d\n", x);
printf("Valoarea lui y=%d, preluata de la y=*ip\n", y, y=*ip);
*ip=0;
printf("Valoarea lui x=%d si este preluata de la *ip=%d\n", x, *ip=0);
printf("Valoarea lui z=%d este decrementata cu 1 \n", --*ip);
return 0;
}
Un pointer este o variabilă a cărei valoare este adresa altei variabile, adică adresa
directă a locației memoriei. Ca orice variabilă sau constantă, trebuie declarat un
pointer înainte de a fi utilizat pentru a stoca orice adresă variabilă.
Forma sintactică a unui pointer este:
tip *numele-variabilei;

tip este tipul de bază al pointerului, care trebuie să fie un tip de date C valid
numele-variabilei este numele variabilei indicatorului
Asteriscul * utilizat pentru a declara un pointer, același cu cel utilizat pentru
multiplicare, dar în acest fel este utilizat pentru a desemna o variabilă ca un pointer.
int *ip; /* pointer pentru un integer */
double *dp; /* pointer pentru un double */
float *fp; /* pointer pentru un float */
char *ch; /* pointer pentru un character */

Un pointer returnează același tip de dată, pentru un int, float, char sau oricare
altul, este același, un număr hexazecimal de tip long care reprezintă o adresă de
memorie.
Singura diferență dintre pointerii de diferite tipuri de date este tipul de date al variabilei
sau constantei care indică pointerul.
Există câteva operațiuni importante, utilizate frecvent:
a) definim o variabilă pointer
b) atribuim adresa unei variabile unui pointer
c) accesarea valorii adresei disponibile în variabila pointer

Acest lucru se face prin utilizarea operatorului unar * care returnează valoarea
variabilei localizate la adresa specificată de operator.
#include <stdio.h>

int main ()
{
int x = 20; /* declaratie variabila efectiva */
int *ip; /* declaratie variabila pointer */
ip = &x; /* adresa depozitului x in variabila pointer */
printf("Adresa variabilei x: %x\n", &x);
/* adresa stocata in variabila pointer */
printf("Adresa stocata in variabila ip: %x\n", ip);
/* accesarea valorii utilizand pointer */
printf("Valoarea variabilei *ip: %d\n", *ip);
return 0;
}
Se poate declara un pointer cu o valoare NULL, care returnează 0.
În acest caz nu există o adresă exactă căruia să îi fie atribuită.
Acest lucru se face în momentul declarării variabilei.
Un pointer căruia i se atribuie NULL se numește pointer nul.
Pointerul NULL este o constantă cu o valoare zero definită în mai multe biblioteci
standard în C.
#include <stdio.h>

int main ()
{
int *p = NULL;
printf("Valoarea lui p este: %x\n", p);
return 0;
}
În majoritatea sistemelor de operare, programele nu au permisiunea de a accesa
memoria la adresa 0, deoarece acea memorie este rezervată de sistemul de operare.
Cu toate acestea, adresa de memorie 0 are o semnificație specială:
• semnalează faptul că pointerul nu este destinat să arate spre o locație de memorie
accesibilă.

Dar prin convenție, dacă un pointer conține valoarea nulă (zero), se presupune că nu
indică spre nimic.
Pentru a verifica dacă există un pointer nul, se poate utiliza una dintre instrucțiunile
următoare:
if(p) /* arată dacă p nu este nul */
if(!p) /* arată dacă p este nul */
Pointerii au multe concepte (ușor de înțeles) și sunt foarte importante pentru
programarea C.
Pointer aritmetic Există patru operatori aritmetici care pot fi utilizați
împreună cu pointerii: ++, --, +, -
Matrice de pointeri Se poate defini o matrice pentru a reține un număr
oarecare de pointeri
Pointer la pointer În C există posibilitatea de a avea un pointer la un pointer

Pointer ca argument al unei Trecerea unui argument prin referință sau prin adresă
funcții permite modificarea argumentului transmis în funcția de
apelare, de către funcția apelată.
Funcții care returnează pointeri C permite unei funcții să returneze un indicator variabilei
locale, variabilei statice și memoriei alocate dinamic
Un pointer în C este o adresă, care este o valoare numerică, de aceea, aveți
posibilitatea să efectuați operații aritmetice pe un pointer, la fel ca pe o valoare
numerică.
Cei patru operatori aritmetici care pot fi utilizați pe pointeri: ++, --, +, și -
Pentru a înțelege pointerul aritmetic, să luăm în considerare faptul că p este un
pointer întreg care indică adresa 1000.
Presupunând că operăm cu numere întregi pe 32 de biți, și că efectuăm o
incrementare a pointerului: p++
După operația de incrementare, p va indica locația 1004, deoarece de fiecare dată
când p este incrementat, acesta va indica următoarea locație întreagă, care este
de 4 octeți lângă locația curentă. Această operație va muta pointerul la următoarea
locație de memorie, fără a afecta valoarea reală a locației de memorie.
Dar dacă p indică spre un caracter a cărui adresă este 1000, atunci operațiunea de
mai sus va indica locația 1001, deoarece următorul caracter va fi disponibil la 1001.
Este de preferat să se folosească un pointer în locul unui tablou, deoarece variabila
pointer poate fi incrementată, spre deosebire de numele matricei (a tabloului) care
nu poate fi incrementat, deoarece acesta este o constantă pointer.
#include <stdio.h> /* mutare la locatia urmatoare */
const int MAXIM = 3; p++;
}
int main() return 0;
{ }
int sir[]={1,2,3,4,5};
int i, *p;
/* se preia adresa matricei in pointer */
p = sir;
for(i=0;i<MAXIM;i++){
printf("Adresa pentru sir[%d] =
%x\n", i, p);
printf("Valoarea pentru sir[%d]
= %d\n", i, *p);
Aceleași considerații se aplică în cazul decrementării unui pointer, care scade
valoarea sa cu numărul de octeți ai tipului său de date
#include <stdio.h> /* se muta in locatia precedenta */
const int MAXIM = 3; p--;
}
int main() return 0;
{ }
int sir[] = {1,2,3,4,5};
int i, *p;
/* se preia adresa matricei in pointer */
p = &sir[MAXIM-1];
for(i=MAXIM;i>0;i--){
printf("Adresa pentru sir[%d] =
%x\n", i-1, p);
printf("Valoarea pentru sir[%d]
= %d\n", i-1, *p);
Pointerii pot fi comparați prin utilizarea operatorilor relaționali, precum ==, <, și >.
Dacă p1 și p2 sunt pointeri care sunt legați între ei, ar fi elemente ale aceleiași
matrice.
Următorul program modifică exemplul anterior, unul prin incrementarea variabilei
pointer, atât timp cât adresa pe care o indică este fie mai mică sau egală cu adresa
ultimului element al matricei, care este &sir[MAXIM - 1]
#include <stdio.h> /* se indica spre urmatoare locatie */
const int MAXIM = 5; p++;
int main() { i++;
int sir[] = {1,2,3,4,5}; }
int i, *p; return 0; }
/* se preia adresa primului element in
pointer */
p = sir;
i = 0;
while(p<=&sir[MAXIM - 1]){
printf("Adresa pentru sir[%d] =
%x\n", i, p);
printf("Valoarea pentru sir[%d]
= %d\n", i, *p);
Poate exista o situație în care dorim să menținem o matrice (un tablou de date), care
poate stoca pointeri ca un int sau char sau orice alt tip de date disponibile.
Sintaxa pentru declararea unei serii de pointeri la un întreg:
int *p[MAXIM];

Acesta declară p ca o serie de MAXIM pointeri întregi. Astfel, fiecare element din p,
deține un indicator la o valoare int.
Un exemplu, care utilizează o matrice de 3 numere întregi:
#include <stdio.h>
const int MAXIM = 3;

int main()
{
int sir[] = {1,2,3};
int i;
for(i=0;i<MAXIM;i++)
{
printf("Valoarea pentru sir[%d] = %d\n", i, sir[i]);
}
return 0;
}
Următorul exemplu utilizează 3 numere for(i=0;i<MAXIM;i++)
întregi, care sunt stocate într-o matrice de {
pointers, după urmează: printf("Valoarea pentru sir[%d]
#include <stdio.h> = %d\n", i, *p[i] );
const int MAXIM = 3; }
return 0;
int main() }
{
int sir[] = {1,2,3};
int i, *p[MAXIM];
for(i=0;i<MAXIM;i++)
{
// atribuirea adresei pentru integer
p[i]=&sir[i]; }
De asemenea, se pot utiliza o serie de int i=0;
pointeri pentru a stoca o listă de șiruri de for(i=0;i<MAXIM;i++)
caractere: {
#include <stdio.h> printf("Valoarea pentru
const int MAXIM = 4; nume[%d] = %s\n", i, nume[i]);
}
int main() return 0;
{ }
char *nume[] = {
"ABC",
"DEF",
"GHI",
"JKL"
};
Un pointer la un pointer reprezintă o serie de interacțiuni care pot crea un lanț de
pointeri. În mod normal, un pointer conține adresa unei variabile. Când definim un
pointer la un pointer, primul pointer conține adresa celui de-al doilea pointer, care
indică locația care conține valoarea reală a unei variabile.

Pointerul Pointerul Variabila


→ →
Adresă Adresă Valoare

O variabilă care este un pointer la un pointer trebuie să fie declarată ca atare.


Acest lucru se face prin plasarea unui asterisc * suplimentar în fața numelui său.
Sintaxa următoare este pentru declararea un pointer la un pointer de tipul int:
int **variabila;
Atunci când o valoare țintă este indicată indirect de un pointer la un pointer,
accesarea acestei valori necesită aplicarea de două ori a operatorului asterisc *.
#include <stdio.h> printf("Valoarea pentru x =
int main() %d\n", x);
{ printf("Valoare disponibila la
int x; *p = %d\n", *p);
int *p; printf("Valoare disponibila la
int **pp; **pp = %d\n", **pp);
x = 2021; return 0;
}
/* sa ia adresa variabilei x */
p=&x;
/* ia adresa p folosind adresa prin
operatorul & */
/* ia valoarea utilizand pp */
pp=&p;
Programarea în C permite trecerea unui pointer către o funcție.
Pentru a face acest lucru, se declară parametrul funcției ca un pointer.
Se trece un pointer unsigned long la o funcție, apoi i se va schimba valoarea în
interiorul funcției, iar rezultatul se va returna funcției de apelare.
#include <stdio.h> void getSeconds(unsigned long
#include <time.h> *p)
void getSeconds(unsigned long {
*p); /* obțineți numărul curent de secunde */
*p = time(NULL);
int main () return;
{ }
unsigned long sec;
getSeconds(&sec);
/* imprimarea valorii reale */
printf("Numărul de secunde:
%ld\n", sec);
return 0;
}
Funcția, care poate accepta un pointer, poate %.3f\n", avg);
accepta, de asemenea, un tablou return 0;
de date (matrice) }
#include <stdio.h> double getAverage(int *arr, int
/* prototiparea functiei */ size)
double getAverage(int *arr,int {
size); int i, suma=0;
int main(){ double avg;
/* o matrice int cu 5 elemente */ for(i=0;i<size;++i)
int balanta[5] = {2176,2,32,7,55}; {
double avg; suma += arr[i];
/* trecere indicator la matrice ca argument }
*/ avg=(double)suma/size;
avg = getAverage(balanta, 5); return avg;
/* iesirea valorii returnate */ }
printf("Valoarea medie este:
În C se permite returnarea unui pointer dintr-o funcție.
Pentru a face acest lucru, va trebui să declare o funcție de returnare a unui pointer.
int * myFunction()
{
.
.
.
}

Atenție: nu este o idee bună să se returneze adresa unei variabile locale în afara
funcției.
În următorul exemplu o funcție care va genera 10 numere aleatorii și le va returna
utilizând un nume de matrice care reprezintă un pointer, adică adresa primului
element matrice.
#include <stdio.h> /* functia principala de apelare a
#include <time.h> functiei definite deasupra */
/* functia de generare si returnare a int main()
numerelor aleatorii. */ {
int * getRandom( ) { /* un pointer la un int */
static int r[10]; int *p;
int i; int i;
/* se stabilesc numerele */
srand((unsigned) time(NULL)); p = getRandom();
for(i=0;i<10;++i) { for (i=0;i<10;i++)
r[i]=rand(); {
printf(" %d\n", r[i]); printf("*(p+[%d]): %d\n", i,
} *(p+i));
return r; }
} return 0;
}

S-ar putea să vă placă și