Sunteți pe pagina 1din 7

Programarea Calculatoarelor - Limbaje

Lucrarea 09. Pointeri şi operaţii cu ei. Transferul prin adresă a parametrilor


către funcţii

O1. Definirea unui pointer în limbajul C


Obiective O2. Modificarea valorilor stocate în adresele date de pointeri
O3. Operații cu variabile de tip pointer

INTRODUCERE
Un pointer este o variabilă ce conține adresa unei locații de memorie. Conținutul sau valoarea
pointerului este o valoare întreagă fără semn.
Declarare:
tip *nume_pointer;
tip* nume_pointer;

- tipul pointerului specifică dimensiunea de memorie ce va fi citită la utilizarea valorii pointate.


ex:
int n = 99;
int *pn = &n;

IMPORTANT:
declararea unui pointer nu înseamnă și inițializarea sa!!
deoarece un pointer poate accesa orice locație de memorie, este important ca pointerii să nu
fie utilizați înainte de inițializare.
Alternativă - declarare pointer NULL:
int *pnumber = NULL;
NULL e o constantă definită în multiple biblioteci standard (stddef.h, stdlib.h, stdio.h, string.h,
time.h, wchar.h, locale.h) și este echivalentul lui 0 pentru tipuri de date numerice

© Adriana Stan, Ligia Chiorean, Mircea Vaida 1 Programarea Calculatoarelor - Limbaje


Operatori specifici pointerilor
Operatorul & (adresare sau referențiere):
• permite aflarea adresei unei variabile oarecare: &nume_var
• rezultatul este un pointer la tipul variabilei

Operatorul * (indirectare sau dereferențiere):


• se foloseşte pentru a afla valoarea stocată la o adresă:
*nume_pointer
• expresia *nume_pointer poate fi folosită atât pentru a obține valoarea obiectului, cât şi pen-
tru a o modifica:
var = *nume_pointer ;
*nume_pointer = expr;
• orice variabilă pointer trebuie definită cu o valoare validă (0 sau NULL nu e validă, deci cu
adresa unei date) înainte de a fi utilizată
• în C/C++ se permite ca orice tip de pointer să pointeze oriunde în memorie, tipul pointerului
determinând modul în care va fi tratat obiectul pointat;
• un pointer de un anumit tip nu trebuie folosit ca să pointeze o dată de alt tip:

Pointerii generici nu sunt asociați unui anumit tip de date:


void *ptr;
• dimensiunea zonei de memorie adresate şi interpretarea datelor din acea zonă nu sunt
definite!!
• pot fi utilizați cu mai multe tipuri de date, însă numai cu operatorul de conversie explicită
(cast)

Operații cu pointeri
În operații se ține cont de faptul că adresele din pointeri au valori numerice întregi fără semn

Operație Definiție

Atribuire Dacă:
tip1 *id_ptr1;
tip2 *id_ptr2;
id_ptr1 = id_ptr2;

Avem următoarele cazuri:


• tip1 si tip2 sunt identice, atribuirea este corectă
• tip1 este void, atunci tip2 poate fi oarecare;
• tip2 este void, atunci tip1 poate fi oarecare (la asignare se foloseste
cast);
• tip1 si tip2 diferă, atunci compilatorul generează un avertisment sau o
eroare

© Adriana Stan, Ligia Chiorean, Mircea Vaida 2 Programarea Calculatoarelor - Limbaje


Comparare Se face cu operatorii relaționali. Se poate realiza doar în cazul în care
pointerii pointează pe obiecte de acelaşi tip.
Operatorii == şi != pot fi folosiți pentru a compara pointeri cu constanta
specială NULL.

Pentru un pointer generic (void *p) se pot face comparațiile:


p == NULL
p != NULL

Adunare, scădere, Pot fi adăugate sau scăzute doar cantități întregi. Operațiile se efectuează
incrementare, relativ la tipul pointerului (int, float, char, etc.)
decrementare
Fie declarația:
tip *id_ptr;
Operațiile:
id_ptr+n, id_ptr-n
corespund adăugării/scăderii la adresa obținută în cadrul variabilei id_ptr a
valorii: n*sizeof(tip).
Analog se efectuează şi operațiile de incrementare/decrementare doar că
n este= 1/-1.
Rezultatul este corect doar atunci când pointerul adresează un tablou și
prin operatia aritmetică se produce o deplasare în interiorul limitelor
tabloului.
Operația de incrementare/decrementare se poate aplica: asupra pointeru-
lui însuşi; asupra valorii la care pointează.

OBSERVAȚII
• Scăderea a doi pointeri este permisă numai pentru pointeri de acelaşi tip ce referă un tablou,
rezultatul fiind o valoare care reprezintă diferența de adrese divizată la dimensiunea tipului de
bază (sizeof())
• Adunarea pointerilor NU este permisă !
• Datorită priorității tipului pointerului la adunare şi scădere, operanzii NU pot fi pointeri void sau
pointeri spre funcții!

Apelul funcțiilor folosind pointeri


Dacă vrem ca o funcție să modifice o variabilă parametru efectiv, atunci trebuie să transmitem
funcției, la apel, adresa variabilei. Ca parametri formali se pot folosi pointeri, în care se vor copia
aceste adrese.
Pentru a utiliza ca argument un tablou, funcția va primi doar adresa acelui tablou, adică adresa
primului element din tablou.

Variante:
• parametrul formal este declarat ca un tablou fără dimensiune
int cauta(int p[], int n, int x );

© Adriana Stan, Ligia Chiorean, Mircea Vaida 3 Programarea Calculatoarelor - Limbaje


• parametrul formal este declarat ca un pointer de tipul tabloului, argumentul folosit ca şi para-
metru efectiv fiind adresa tabloului asupra căruia se fac operații în funcție
int cauta(int *p, int n, int x );

Pointeri constanți și pointeri către constante

Pointeri către constante


const char *str1 = "pointer catre constanta";
//str1[0] = 'P'; // incorect
str1 = "ptr la const"; // ok

Pointeri constanți (nu pot fi modificați)


char *const str2 = "pointer constant ";
//str2 = "ptr const"; // incorect
str2[0] = 'P'; // ok

Pointeri constanți către constante


const char *const str3 = "pointer constant la constanta";
//str3 = "ptr const la const";// incorect
//str3[0] = 'C'; // incorect

Un pointer poate, indirect, să modifice o variabilă declarată cu modificatorul const, folosind ex-
presia:
*(tip *)&var;
NOTĂ! Modificarea se poate face într-o altă funcție, constanta îşi va păstra valoarea în funcția
în care a fost declarată

EXEMPLE

1. Declarare pointeri, utilizarea operatorilor de adresare şi indirectare

#include <stdio.h>

int main(void){
int i = 10, j=50;
int *iptr; // declarare pointer

iptr = &i; // definire prin asignare pointer


printf("Adresa din iptr: %p \n", iptr);
printf("Valoarea de la adresa *iptr: %d\n", *iptr);

*iptr = 25; // se modifica valoarea din memorie


printf("Noua valoare din memorie este: %d\n", i);

iptr = &j; // reasignare pointer


printf("\nAdresa din iptr: %p \n", iptr);

© Adriana Stan, Ligia Chiorean, Mircea Vaida 4 Programarea Calculatoarelor - Limbaje


printf("Valoarea de la adresa *iptr: %d\n", *iptr);

*iptr = 25; // se modifica valoarea din memorie


printf("Noua valoare din memorie este: %d\n", j);
}

2. Pointeri și operatorul cast


#include <stdio.h>

void baza2 (unsigned int);

int main(void){
int n, *pn;
float r, *pr;
printf("\nIntroduceti un numar intreg: ");
scanf("%d", &n);
pn = &n;
printf("\nReprezentarea in memorie a lui %d in hexa %x",n, n);
printf("\nReprezentarea pe bytes: 0x%02x %02x %02x %02x\n",
*((unsigned char *)pn+3), *((unsigned char *)pn+2),
*((unsigned char *)pn+1), *((unsigned char *)pn));
printf("\n Bitii baza 2 : ");
baza2(n);

printf("\nIntroduceti un numar real: ");


scanf("%f", &r);
pr = &r;
printf("\nReprezentarea in memorie a lui %f in hexa %a", r, r);
printf("\nReprezentarea pe bytes: 0x%02x %02x %02x %02x",
*((unsigned char *)pr+3), *((unsigned char *)pr+2),
*((unsigned char *)pr+1), *((unsigned char *)pr));
}//main

void baza2 (unsigned int a){


if(a!=0)
baza2(a>>1);
printf("%d ", a%2);
}//baza2

3. Operaţii cu pointeri

#include <stdio.h>

int main(void){
int *pt_int;
float *pt_float;
int i = 10, j = 20;
float x = 1.2345, y = 32.14;
void *general;//pointer generic

pt_int = &i;
*pt_int += j;
© Adriana Stan, Ligia Chiorean, Mircea Vaida 5 Programarea Calculatoarelor - Limbaje
printf( "Valoarea lui i devine: %d\n", *pt_int);

general = pt_int;
*(int *)general = 0;
printf("Ultima valoare pentru i este: %d\n", i );

pt_float = &x;
y += 5 * (*pt_float);
printf("Valoarea lui y este: %f\n", y);

general = pt_float;
*(float *)general = 1.1;
printf("Ultima valoare pentru x este: %f", x);
}

4. Transmiterea parametrilor prin adresă

#include <stdio.h>

void Swap1 (int x, int y);


void Swap2 (int *x, int *y);

int main (void){


int i = 10, j = 20;
Swap1(i, j);
printf("i = %d, j = %d\n", i, j);

Swap2(&i, &j);
printf("i = %d, j = %d \n", i,j);
}

void Swap1 (int x, int y){


int temp = x;
x = y;
y = temp;
}

void Swap2 (int *x, int *y){


int temp = *x;
*x = *y;
*y = temp;
}

TEME
1. Să se scrie un program care citeşte de la tastatură un şir de caractere, apoi elimină din şir
caracterele care se repetă şi afişează în final şirul obţinut, folosind pointeri.
2. Să se scrie un program care citeşte de la tastatură două şiruri de caractere şi afişează
numărul de caractere prin care ele diferă (adică numărul de caractere care există în primul şi nu
există în al doilea plus numărul de caractere care există în al doilea şi nu există în primul).
Folosiţi pointeri pentru accesul la elementele tablourilor.

© Adriana Stan, Ligia Chiorean, Mircea Vaida 6 Programarea Calculatoarelor - Limbaje


3. Să se scrie un program care citeşte elementele a două tablouri unidimensionale de numere
întregi şi afişează produsul scalar al acestora. Se va folosi o functie care preia elementele de la
tastatură şi o altă funcţie, care calculează produsul scalar. Ambele vor utiliza pointeri. Citirea
numărului de elemente ale tabloului şi afişarea rezultatului se va face în funcţia main().
4. Să se scrie o aplicaţie în care se generează aleator 20 de numere întregi cu valori mai mici
decât 50 (Folositi srand(), rand() si operatorul %). Să se scrie o funcţie care elimină din tabloul
unidimensional creat numerele impare. Funcţia va utiliza pointeri. Afişati în main() tabloul iniţial şi
cel obţinut după eliminarea elementelor impare.
5. Să se scrie un program în care se citesc de la tastatură numere reale, ce vor fi stocate într-un
tablou unidimensional. Să se scrie o funcţie care copiază într-un alt tablou toate valorile din
primul tablou, care sunt mai mari decât valoarea medie a numerelor preluate. Se vor folosi point-
eri şi se vor afişa în main() valorile din cele două tablouri.
6. Să se scrie o aplicaţie C/C++ care citeşte de la tastatură un şir de caractere. Să se scrie o
funcţie care afişează caracterele ce compun şirul şi numărul de apariţii ale fiecăruia, folosind
pointeri.

© Adriana Stan, Ligia Chiorean, Mircea Vaida 7 Programarea Calculatoarelor - Limbaje

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