Sunteți pe pagina 1din 39

Scopul cursului

Pointeri
 Definirea și inițializarea pointerilor

 Restricții la folosirea pointerilor

 Relația dintre pointeri și tablouri

 Crearea tablourilor de pointeri

 Indirectarea multiplă

 Alocarea dinamică

 Pointeri către funcții

Programarea calculatoarelor I - Gyorodi


Cornelia 1
Definirea și inițializarea pointerilor
 Un pointer este o variabilă care conţine adresa de memorie a unui obiect.
 De exemplu, dacă o variabilă numită p conţine adresa unei variabile numită
q, spunem că p punctează pe q.
Forma generală de declarare a unui pointer este:
type * var_nume;

unde:
- type - este tipul pointerului şi specifică tipul obiectului pe care pointerul îl
poate puncta
- var_nume - numele pointerului;

Programarea calculatoarelor I - Gyorodi


Cornelia 2
Definirea și inițializarea pointerilor
 Un pointer este asociat unui tip de variabile: există pointeri către char, int,
float etc.
 Dacă T este un tip de date standard sau definit de utilizator, un pointer
către tipul T se declară prin:
T *p;

 Câteva exemple de declaraţii de pointeri:


int *pi;
float *pf;
char *pc;

Programarea calculatoarelor I - Gyorodi


Cornelia 3
Definirea și inițializarea pointerilor

 Există câteva operații importante, pe care le vom face cu ajutorul


pointerilor:
 Definim o variabilă pointer
 Atribuim adresa unei variabile unui pointer
 Accesăm valoarea de la adresa indicată de variabila pointer. Acest lucru
se face prin utilizarea operatorului unar * care returnează valoarea
variabilei situată la adresa specificată de operandul său.

Programarea calculatoarelor I - Gyorodi


Cornelia 4
Definirea și inițializarea pointerilor
 Pentru variabilele de tip pointer există doi operatori specifici, şi anume:
 operatorul de referenţiere & sau de adresare
 operatorul de dereferenţiere * sau de indirectare

 Operatorul & returnează adresa variabilei pe care o precede.


 Operatorul * returnează valoarea de la adresa variabilei pe care o precede.

Programarea calculatoarelor I - Gyorodi


Cornelia 5
Definirea și inițializarea pointerilor
 Variabile Pointer
 Contin adresa de memorie a variabilei

int count = 7, count


*countPtr; 7

 Pointerii conțin adresa unei variabile care are o valoare specificată


 Indirectarea – referirea prin pointer a valori variabilei

countPtr count
countPtr = &count; 7

Programarea calculatoarelor I - Gyorodi


Cornelia 6
Definirea și inițializarea pointerilor

 Inițializarea unui pointer cu adresa unei variabile se


realizează astfel:

type var,* var_pointer;


var_pointer = &var;

Programarea calculatoarelor I - Gyorodi


Cornelia 7
Definirea și inițializarea pointerilor
 Când valoarea unei variabile este referită printr-un pointer, procesul
este numit indirectare

void main ( void){


int *p, q;
q = 10;
p = &q; /* asignam lui p adresa lui q */
printf ("%d", *p); /*afisam valoarea lui q folosind pointerul p */
}

Programarea calculatoarelor I - Gyorodi


Cornelia 8
Operatorii pointer
 & (address operator)
 Returnează adresa unei variabile
int y = 5;
int *yPtr;
yPtr = &y; // yPtr indică adresa lui y
//yPtr “puncteza la” y

y yptr y
5 500000 600000 600000 5
yPtr

Adresa lui y
este valoarea
lui yptr
Programarea calculatoarelor I - Gyorodi
Cornelia 9
Exemplu – Utilizarea pointerilor

#include <stdio.h>
int main () {
int var = 20;
int *ip; /* declarea unei variable pointer */
ip = &var; /* initializarea variabilei pointer*/
printf("Adresa variablei: %x\n", &var ); printf("Adresa stocata in
variabila ip : %x\n", ip );
printf("Value of *ip variable: %d\n", *ip ); /* accesarea valori
variabilei utilizand un pointer */
return 0;
}

Programarea calculatoarelor I - Gyorodi


Cornelia 10
Pointerul NULL

 Este întotdeauna o practică bună să atribuiți o valoare NULL


unei variabile pointer în cazul în care nu aveți o adresă exactă
de atribuit.
 Acest lucru se face în momentul declarării variabilei.
 Un pointer căruia i se atribuie NULL se numește pointer nul.
int *ptr = NULL;

Programarea calculatoarelor I - Gyorodi


Cornelia 11
Operatorii pointer
 Cei doi operatori, & şi * sunt operatori inverşi:
 dacă x este de tip T1 atunci *(&x) este identic cu x,
 dacă px este de tip T2*, atunci &(*px) este identic cu px.
 pointerii reprezintă adrese ale unor zone de memorie;
 putem avea acces la acele zone prin operatorul *;
 dimensiunea şi semnificaţia unei zone indicate de un pointer depinde de
tipul pointerului.
 Dacă pointerul p indică o variabilă x, atunci expresia *p poate apărea în
orice context în care este permisă apariţia lui x.

Programarea calculatoarelor I - Gyorodi


Cornelia 12
Exemplu
/**
* Operatorii & si * operators
*/
#include <stdio.h>
#include <stdlib.h>

int main()
{
int a; /* a este un intreg */
int *aPtr; /* aPtr este un pointer la un intreg */

a = 7;
aPtr = &a; /* aPtr setat sa indice adresa lui a */
printf( “Adresa lui a este %p\n Valoarea lui aPtr este %p", &a, aPtr );

printf( "\n\nT Valoarea lui a este %d\nValoarea lui *aPtr este %d", a, *aPtr );

printf( "\n\n Afisam ca operatorii * si & pot fi inversati unul cu altul.\n


&*aPtr = %p“ "\n*&aPtr = %p\n", &*aPtr, *&aPtr );

return EXIT_SUCCESS;
}

Programarea calculatoarelor I - Gyorodi


Cornelia 13
Restricţii la folosirea pointerilor
 Tipul pointerului trebuie să fie acelaşi cu cel al variabilei pe care o punctează.
void main (void){
int *p;
float q, x;
x = 123.45;
p = &x; /* gresit, deoarece p puncteaza numai intregi*/
q = *p; /* incercare de a asigna lui q o valoare folosind indirectarea */
}

 Numai 4 operatori pot fi aplicaţi unui pointer: +, ++, -, --.

int *p, q;
...
p = &q;
p ++; /* pointerul p va indica urmatoarea adresa dupa q */

Programarea calculatoarelor I - Gyorodi


Cornelia 14
Exemplu
 Un exemplu în care un pointer indică obiecte diferite pe parcursul
execuţiei programului:

main()
{
int i=1, j=5, *p=&i;
*p=2;
(*(p=&j))++;
printf(“i=%d j=%d\n”,i ,j);
}

Programarea calculatoarelor I - Gyorodi


Cornelia 15
Aritmetica pointerilor
 5 elemente int ale unui tablou pe un sistem de calcul cu 4
byte pentru intregi
 vPtr indica la primul element v[ 0 ]
 La locatia 3000 (vPtr = 3000)
 vPtr += 2; setază vPtr to 3008
 vPtr indică la v[ 2 ] (incrementat cu 2), dar sistemul are 4 byte pentru int,
așa că el indică la adresa 3008
locatia
3000 3004 3008 3012 3016

v[0] v[1] v[2] v[3] v[4]

variabila pointer vPtr


Programarea calculatoarelor I - Gyorodi
Cornelia 16
Operatorii ++ și -- în lucru cu pointerii
 Este posibil ca operaţiile de incrementare sau decrementare să se aplice
asupra pointerului însuşi sau asupra obiectului pe care îl punctează.
 Exemplu:
int * p, q;
...
q = 10;
p = &q;
*p++; /* p va indica elementul următor */
(*p) ++; /* valoarea indicată de p va fi incrementată, adica q
este incrementat iar p rămâne neschimbat */
printf ("%d", q); /* se va tipări 11, deoarece valoarea lui q a fost
incrementată */

 În instrucţiunea (*p) ++, parantezele fac ca valoarea (punctată) indicată de p să fie incrementată

Programarea calculatoarelor I - Gyorodi


Cornelia 17
Pointerii și operatorii
 Diferența dintre doi pointeri
 Returnază numărul de elemente de la unul la celălalt
 Dacă
vPtr2 = v[ 2 ];
vPtr = v[ 0 ];
 vPtr2 - vPtr va fi 2
 Compararea Pointererilor ( <, == , > )
 Verifică care pointer indică la cel mai mare element al tabloului
 Deasemenea , verifică dacă un pointer indică la 0

Programarea calculatoarelor I - Gyorodi


Cornelia 18
Folosirea pointerilor către tablouri
 În limbajul C, pointerii şi tablourile sunt în strânsă legătură ei fiind de fapt interschimbabili.
 Numele unui tablou fără index, generează un pointer către primul element al tabloului.

void main(void ){
char sir[80];
int i;
gets(sir);
for (i = 0; sir[i]; i++)
printf ("%c", sir[i]);
}

Programarea calculatoarelor I - Gyorodi


Cornelia 19
Folosirea pointerilor către tablouri
int a[10]= {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
void main (void )
{
int *p;
p = a; /* asignam lui p adresa de start al tabloului a */
/* afisam primele trei elemente ale tabloului a */
printf ("%d %d %d \n", *p, *(p+1), *(p+2));
printf ("%d %d %d \n", a[0], a[1], a[2]); /* afiseaza
acelasi informatii */
}

Programarea calculatoarelor I - Gyorodi


Cornelia 20
Tablouri de pointeri
 Tablourile pot conține pointeri
 De exemplu: un tablou de șiruri
char *suit[ 4 ] = { "Hearts", "Diamonds", "Clubs", "Spades" };
 Strings sunt pointer la primul caracter
 char * – fiecare element al tabloului suit este un pointer la caracter
 Șirul nu este memorat în tabloul suit, numai pointeri la șiruri sunt memorați
suit[0] ’H’ ’e’ ’a’ ’r’ ’t’ ’s’ ’\0’
suit[1] ’D’ ’i’ ’a’ ’m’ ’o’ ’n’ ’d’ ’s’ ’\0’
suit[2] ’C’ ’l’ ’u’ ’b’ ’s’ ’\0’
suit[3] ’S’ ’p’ ’a’ ’d’ ’e’ ’s’ ’\0’

 Tabloul suit are o dimensiune fixă, dar șirurile pot avea orice dimensiune

Programarea calculatoarelor I - Gyorodi


Cornelia 21
Crearea tablourilor de pointeri
 Pointerii pot forma tablouri, ca orice alt tip de dată.
Exemplu:
int *p[10]; /* declară un tablou de pointeri de tip int de 10 elemente.*/
p[8] = &a; /* adresa variabilei a este asignată elementului 9 al tabloului.*/

 Pentru a asigna întregului punctat de al treilea element al tabloului p


valoarea 100, trebuie folosită instrucţiunea:
*p [2] = 100;

Programarea calculatoarelor I - Gyorodi


Cornelia 22
Indirectarea multiplă

 În C este posibil să avem un pointer care să puncteze un alt pointer. Acest


proces se numeşte indirectare multiplă.
 Pentru a declara un pointer către alt pointer folosim sintaxa generală:
type **variabila;

char **mp, *p, ch;


p = &ch; /* asignează lui p adresa lui ch */
mp = &p; /* asignează lui mp adresa lui p */
**mp = 'A'; /* asignează lui ch valoarea lui 'A' folosind indirectarea multiplă */

Programarea calculatoarelor I - Gyorodi


Cornelia 23
Exemplu - Indirectarea multiplă
#include <stdio.h>
int main () {
int var;
int *ptr;
int **pptr;
var = 3000;
/* take the address of var */
ptr = &var;
/* take the address of ptr using address of operator & */
pptr = &ptr;

/* take the value using pptr */


printf("Value of var = %d\n", var );
printf("Value available at *ptr = %d\n", *ptr );
printf("Value available at **pptr = %d\n", **pptr);
return 0;
}
24
Exemplu: Afişează şirul introdus mai întâi cu litere mari şi apoi cu litere mici.
# include <ctype.h>
# include <stdio.h>
void main (void ){
char str[80];
char *p;
printf ("Introduceti un sir:");
gets (str);
p = str;
while (*p)
{
*p = toupper (*p);
p++;
}
printf ("%s\n", str); /* afisare cu litere mari */
p = str;
while (*p)
{
*p = tolower (*p);
p++;
}
printf ( "%s\n", str); /* afisare cu litere mici */
}

Mai multe detalii în Bibl 1 - Exemplu 6.6


25
Transmiterea de pointeri către funcții în C
 Limbajul C permite trecerea unui pointer către o funcție. Pentru a face acest lucru, pur și
simplu declarați parametrul funcției de tip pointer.
 Funcția, care poate accepta un pointer, poate accepta și un tablou, așa cum se arată în
exemplul următor.

#include <stdio.h> double getAverage(int *arr, int


/* function declaration */ size)
double getAverage(int *arr, int size); {
int main () { int i, sum = 0;
int balance[5] = {1000, 2, 3, 17, 50}; double avg;
double avg; for (i = 0; i < size; ++i)
sum += arr[i];
/* functia este apelata cu un argument de tip tablou */
avg = getAverage( balance, 5 ) ; avg = (double)sum / size;
return avg;
printf("Average value is: %f\n", avg ); }
return 0;
}

26
Returnarea unui pointer dintr-o funcție
 Limbajul C permite și returnarea unui pointer dintr-o funcție. Pentru a face acest lucru, ar
trebui să declarați o funcție care returnează un pointer ca în exemplul următor:
int * myFunction() {
. . .
}

 Nu este o idee bună să returnați adresa unei variabile locale în afara funcției, așa că ar
trebui să definiți variabila locală ca variabilă statică.
 Exemplu: #include <stdio.h>
#include <time.h>
/* function to generate and return random numbers. */
int * getRandom( ) {
static int r[10];
int i;
srand( (unsigned)time( NULL ) ); /*uses the value of the system timer/counter as
the random seed.*/
for ( i = 0; i < 10; ++i) {
r[i] = rand();
printf("%d\n", r[i] );
}
return r;
}
27
Exemplu - Returnarea unui pointer dintr-o funcție

#include <stdio.h>
#include <time.h> int main () {
/* function to generate and return random /* a pointer to an int */
int *p; int i;
numbers. */
int * getRandom( ) { p = getRandom();
static int r[10];
int i; for ( i = 0; i < 10; i++ )
srand( (unsigned)time( NULL ) ); printf("*(p + [%d]) : %d\n", i, *(p + i) );
for ( i = 0; i < 10; ++i) {
r[i] = rand(); return 0;
}
printf("%d\n", r[i] );
}
return r;
}

Programarea calculatoarelor I - Gyorodi


Cornelia 28
Alocarea dinamică
 Alocarea dinamică este procesul prin care memoria este alocată, după necesităţi, în
timpul execuţiei.
 Principalele funcţii pentru alocare dinamică ale limbajului C sunt:
 void *malloc(size_t size); - alocă memoria de dimensiune size
 void free(void *address); - eliberează memoria specificată de adresă.
 void *calloc(int num, int size); - alocă o matrice de num elemente, fiecare element
având dimensiunea size.
 void *realloc(void *adresă, int newsize); - realocă memoria extinzând-o până la
dimensiunea newsize

 Funcţia malloc( ) returnează un pointer la începutul zonei de memorie alocată. Dacă


malloc( ) nu găseşte suficientă memorie liberă pentru a putea fi alocată, atunci se
returnează un pointer null.
 Pentru a elibera memoria, trebuie apelată funcţia free( ) cu un pointer către
începutul blocului de memorie (alocat anterior cu malloc()) care se doreşte a fi
eliberat.

Programarea calculatoarelor I - Gyorodi


Cornelia 29
Exemplu - Alocarea dinamică
# include <stdio.h>
# include <stdlib.h>

int main(void){
char *p;

p = (char*) malloc(80*sizeof(char)); /*alocam memorie pentru 80 de caractere*/


if(!p){
printf("Memorie insuficienta :\n");
exit(1);
}
printf("introduceti un sir :");
gets(p); /*functie de biblioteca care citeste un sir de caractere*/
printf("%s", p);
free(p); /*eliberam memoria alocata */
}
Mai multe detalii în Bibl 1 - Exemplu 6.7
Programarea calculatoarelor I - Gyorodi
Cornelia 30
Exemplu - Alocarea dinamică, creșterea dimensiuni
memoriei
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char name[100];
char *description;
strcpy(name, "Paula Alex");
/* allocate memory dynamically */
description = malloc( 30 * sizeof(char) );
if( description == NULL )
fprintf(stderr, "Error - unable to allocate required memory\n");
else
strcpy( description, " Paula Alex is a student.");
/* suppose you want to store bigger description */
description = realloc( description, 100 * sizeof(char) );
if( description == NULL )
fprintf(stderr, "Error - unable to allocate required memory\n");
else
strcat( description, "She is in class 10th");
printf("Name = %s\n", name );
printf("Description: %s\n", description );
/* release memory using free() function */
free(description); Programarea calculatoarelor I - Gyorodi
} Cornelia 31
Alocarea dinamică în C++
 În C++ este posibilă inţializarea pointerilor prin alocarea unei zone de memorie, folosind
operatorul new.
 Sintaxa pentru folosirea acestui operator este:

tip_ptr=new type; /*fără precizarea valorii iniţiale; */


tip_ptr=new type(valoare); /*cu precizarea valorii iniţiale; */
tip_ptr=new type[dim]; /*pentru alocarea a dim elemente; */

 Alocarea memoriei pentru un vector cu 10 componente numere întregi se face astfel:

int *v=new int[10];

Programarea calculatoarelor I - Gyorodi


Cornelia 32
Alocarea dinamică în C++
 Eliminarea variabilelor dinamice se face cu ajutorul operatorului delete.
 Acesta este complementarul operatorului new şi are sintaxa:
delete variabila;

 Ștergerea memoriei alocate pentru vectorul v cu 10 componente numere


întregi, din exemplul precedent, se face astfel:

delete v;

Programarea calculatoarelor I - Gyorodi


Cornelia 33
Pointeri către funcţii
 Un pointer către o funcţie este o variabilă care conţine adresa punctului de intrare al
funcţiei.

 Când compilatorul compilează un program, el crează câte un punct de intrare pentru


fiecare funcţie din program.
 După ce programul este link-editat, fiecare punct de intrare are o adresă fizică,
adresă care este folosită de fiecare dată când funcţia este referită.
 Deoarece aceasta este o adresă, este posibil să avem un pointer care să o puncteze.
 Având un pointer care punctează o funcţie, devine posibil să apelăm funcţia folosind
pointerul.
 Pentru a crea o variabilă care să poată puncta o funcţie, trebuie declarat un pointer
de acelaşi tip cu tipul funcţiei, urmat de paramertii funcţiei.

Programarea calculatoarelor I - Gyorodi


Cornelia 34
Pointeri către funcţii
 Pentru a crea o variabilă care să poată puncta o funcţie, trebuie declarat un pointer de
acelaşi tip cu tipul funcţiei, urmat de paramertii funcţiei.
 De exemplu, următoarea declaraţie stabileşte că p este un pointer către o funcţie care
returnează un întreg şi are doi parametri întregi a şi b.
int (*p) (int a, int b);
 Pentru a asigna unui pointer adresa unei funcţii, trebuie folosit numele funcţiei fără
paranteze. De exemplu, presupunem că funcţia sum() are prototipul:

int sum(int a, int b);

instrucţiunea de asignare este:


p = sum;

Programarea calculatoarelor I - Gyorodi


Cornelia 35
Exemplu: Programul următor încarcă un tablou de tip int cu 100 numere generate
aleator, îl sortează şi îl afişează sortat.
#include <stdio.h>
#include <stdlib.h>
int comp(int *i, int *j);

int main(void){
int sort[100], i;

for (i = 0; i < 100; i++)


sort[i] = rand();
qsort(sort, 100, sizeof(int), (int (*) (const void*, const void *)) comp);
for (i = 0; i < 100; i++)
printf(“%d\n”, sort[i]);
}
int comp (int *i, int *j){
return *i -*j;
}
Mai multe detalii în Bibl 1 - Exemplu 10.9
36
Funcţia qsort()
 Funcţia qsort() este o rutină de sortare predefinită, care poate sorta orice
tip de tablou cu o singură dimensiune, folosind algoritmul Quicksort.
Prototipul său este:
unde: void qsort(void *array, size_t number, size_t
size, int (*comp) (const void *a, const void *b));

 array - este un pointer către primul element al tabloului ce trebuie sortat


 number - numărul de elemente ale tabloului
 size - dimensiunea unui element al tabloului

Programarea calculatoarelor I - Gyorodi


Cornelia 37
Funcţia qsort()
Parametrul final este un pointer către o funcţie care trebuie creată şi care
compară două elemente ale tabloului, returnând următoarele rezultate:

*a < *b - returneazã o valoare negativã


*a == *b - returneazã zero
*a > *b - returneazã o valoare pozitivã

Programarea calculatoarelor I - Gyorodi


Cornelia 38
Mulțumesc pentru atenție!

Programarea calculatoarelor I - Gyorodi


Cornelia 39

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

  • Problema UBD
    Problema UBD
    Document20 pagini
    Problema UBD
    Bogdan Sopota
    Încă nu există evaluări
  • Proiect Arhitectura Sistemelor de Calcul (DOCA, PATER, KOVACS 1631)
    Proiect Arhitectura Sistemelor de Calcul (DOCA, PATER, KOVACS 1631)
    Document20 pagini
    Proiect Arhitectura Sistemelor de Calcul (DOCA, PATER, KOVACS 1631)
    Bogdan Sopota
    Încă nu există evaluări
  • Curs PCLP
    Curs PCLP
    Document35 pagini
    Curs PCLP
    Bogdan Sopota
    Încă nu există evaluări
  • Curs PCLP
    Curs PCLP
    Document44 pagini
    Curs PCLP
    Bogdan Sopota
    Încă nu există evaluări
  • Curs PCLP
    Curs PCLP
    Document40 pagini
    Curs PCLP
    Bogdan Sopota
    Încă nu există evaluări
  • Curs PCLP
    Curs PCLP
    Document40 pagini
    Curs PCLP
    Bogdan Sopota
    Încă nu există evaluări
  • Curs PCLP
    Curs PCLP
    Document37 pagini
    Curs PCLP
    Bogdan Sopota
    Încă nu există evaluări
  • Curs PCLP
    Curs PCLP
    Document44 pagini
    Curs PCLP
    Bogdan Sopota
    Încă nu există evaluări
  • Curs PCLP
    Curs PCLP
    Document38 pagini
    Curs PCLP
    Bogdan Sopota
    Încă nu există evaluări
  • Curs PCLP
    Curs PCLP
    Document35 pagini
    Curs PCLP
    Bogdan Sopota
    Încă nu există evaluări