<<Pagina Materiale

 
 
 Pointeri 
Definitia pointerilor

Programul si datele sale sunt pastrate in memoria RAM ( Random Access Memory ) a calculatorului.

Definitie:

Un pointer este o variabila care pastreaza adresa unei date, nu valoarea datei.

Un pointer poate fi utilizat pentru referirea diferitelor date si structuri de date. Schimband adresa memorata in pointer, pot fi manipulate informatii situate la diferite locatii de memorie.

Pointerii permit de asemenea crearea de noi variabile in timpul executiei programului, prin alocare dinamica.

In declaratia unei variabile pointer se foloseste operatorul de indirectare *:

       tip_referit * var_pointer; //* este operator de indirectare

Initializarea cu adresa unei variabile:

        tip_referit var,* var_pointer;
     var_pointer=&var;

Valoarea de la adresa indicata de pointer:

        *var_pointer// este de tip_referit

Spatiul ocupat de o variabila pointer:

        sizeof(var_pointer) // valoarea expresiei este 2 ( in modelul small ), oricare ar fi tip_referit
     // expresile de mai jos conduc la aceeasi valoare  2
     sizeof(&var)
        sizeof(tip_referit *)

Tiparirea valorii unui pointer: se foloseste prototipul %p, valoarea aparand sub forma a patru cifre hexa

Adresa unei variabile pointer este un pointer, la fel ca adresa unei variabile de orice alt tip:

       &var_pointer

Observatie:

Un pointer poate fi utilizat doar dupa initializare: prin atribuirea adresei unei variabile sau prin alocare dinamica.

Exemplu:

Programul urmator declara un pointer la intregi, utilizand variabila in toate situatiile prezentate mai sus.

Modificati programul astfel incat variabilele sa devina locale lui main - se vor muta cele doua linii de declaratii din fata, in corpul lui main

Rulati din nou programul si observati cum se schimba informatiile tiparite referitoare la a dresele variabilelor: adresele variabilelor vor fi mai mari dupa modificare; in primul caz, variabilelor li se rezerva spatiu la inceputul segmentului de date - DS, in cazul al doilea, spatiul rezervat va fi pe stiva, la sfarsitul DS. 
 

#include <stdio.h>
#include <conio.h>

int i,*pi;
float f;

void main(void){
  clrscr();

  i=3; pi=&i; // variabila pi se initializeaza cu adresa var i
    // linia de mai sus este echivalenta cu:
    // pi=&i; *pi=3;

    f=-5; 
  printf("i=%d,f=%f,val=%d,pi=%p,adr_i=%p,adr_pi=%p,adr_f=%p\n",
             i,   f,   *pi,   pi,      &i,      &pi,      &f); 

  /* sizeof aplicat unor expresii de tip pointer */
  printf("%d %d %d %d %d %d %d\n",sizeof(int *),sizeof(char *), 
         sizeof(float *),sizeof(&i),sizeof(pi), izeof(&pi),sizeof(&f));

  pi=&f; /* adresa lui f e convertita implicit la pointer la intreg*/
  printf("%p %p %p %p %p %p\n",
          &i,&i+1,pi,pi+1,&f,&f+1); // tipariri de pointeri
  getche();
}

Sus
Alocarea dinamica a memoriei

Functiile de gestionare a memoriei au prototipurile in fisierele header alloc.h sistdlib.h:

        void * malloc(size_t size);

Functia malloc returneaza un pointer la blocul alocat pe heap de dimensiune size, daca un astfel de bloc exista, altfel returneaza NULL.

        void free(void * block);

Functia freeelibereaza blocul alocat anterior cu malloc, avand pointerul transmis ca parametru.

Exemplu:

Programul urmator aloca spatiu pentru o variabila intreaga dinamica,  dupa citire si tiparire, spatiul fiind eliberat. Modificati programul astfel incat variabila dinamica sa fie de tip double. 
 

#include <stdio.h>
#include <alloc.h>
#include <conio.h>

int *pi; // pi este variabila statica

void main(void){
  clrscr();

  pi=(int *)malloc(sizeof(int));
  if(pi==NULL){ 
    puts("*** Memorie insuficienta ***");
    return; // revenire din main
  }

  printf("valoare:");
  scanf("%d",pi);  // citirea variabilei dinamice, de pe heap, de la adresa din pi!!!

  *pi*=2; // dublarea valorii

  printf("val=%d,pi(adresa pe heap)=%p,adr_pi(var statica)=%p\n",
      *pi,   pi,   &pi); 

  /* sizeof aplicat unor expresii  */
  printf("%d %d %d\n",sizeof(*pi), sizeof(pi), sizeof(&pi));

  free(pi); //eliberare spatiu

  printf("pi(dupa elib):%p\n",pi); // nemodificat, dar invalid

  getche();
}

Sus
Legatura dintre tablouri si pointeri

Numele unui tablou este un pointer constant spre primul sau element. Expresiile de mai jos sunt deci echivalente:
        nume_tablou        &nume_tablou        &nume_tablou[0]

    *nume_tablou       nume_tablou[0]

Exemplu:

Programul de mai jos citeste si afiseaza elementele a doua tablouri, la primul accesul se face indexat, la al doilea prin pointeri.
 

#include <stdio.h>
#include <conio.h>
#define N 5

int tab1[N],tab2[N];

void citire1(void){ /* citeste elementele lui tab1 prin accesarea indexata
                                        a elementelor */
  int i;
  puts("Introduceti elementele lui tab1:");
  for(i=0;i<N;i++){
    putchar(':');scanf("%d",&tab1[i]);
  } /*for i*/
} /* citire1 */

void tiparire1(void){ /* tipareste elementele lui tab1 prin accesarea indexata
                                           a elementelor */
  int i;
  puts("Elementele lui tab1:");
  for(i=0;i<N;i++)
    printf("%d ",tab1[i]);
  putchar('\n');
} /* tiparire1 */

void citire2(void){ /* citeste elementele lui tab2 - accesarea fiecarui
         element se face printr-un pointer la el */
  int *pi;
  puts("Introduceti elementele lui tab2:");
  for(pi=tab2;pi<tab2+N;pi++){ /* initializari echivalente sunt pi=&tab2 
    sau pi=&tab[0]; conditie echivalenta pi<=&tab2[N-1] */
    putchar(':');scanf("%d",pi);
  } /*for pi*/
} /* citire2 */

void tiparire2(void){ /* tipareste elementele lui tab2 prin accesare
    prin pointeri */
  int *pi;
  puts("Elementele lui tab2:");
  for(pi=tab2;pi<tab2+N;pi++)
    printf("%d ",*pi);
  putchar('\n');
} /* tiparire2 */

void main(void){
  clrscr();

  citire1();
  tiparire1();

  citire2();
  tiparire2();

  getche();
}

Sus
Aritmetica pointerilor

Daca:

      tip_referit * var_pointer;
      int i;

expresia:

      var_pointer+i

este un pointer avand valoarea mai mare decat var_pointer cu sizeof(tip_referit)*n

Exemplu:

#define N 10
float *p,t[N];
int i;

void main(void){
  p=t;  // sau p=&t; sau p=&t[0];
  ...

  //citirea valorii lui t[2]
  scanf("%f",&t[2]); 
  //scanf("%f",p+2); //linie echivalenta cu cea de mai sus

    //tiparirea valorii lui t[2]
  printf("%f",t[2]); 
  //printf("%f",*(p+2)); //linie echivalenta cu cea de mai sus
}

Sus
Quiz

O mica autotestare, dupa rularea si modificarea programelor de mai sus:

1.Secventa de mai jos atribuie valoarea 5 unui intregului de la adresa din pointerul pnr:

int * pnr;
*pnr=5;

2.Pentru tabloul de mai jos, care dintre variante permite initializarea elementului al i-lea cu 10?

#define DIM 10
int i=5, tab[NR];

tab[i-1]=10;
*(tab+i-1)=10;

3.Ce se tipareste pe ecran la executia secventei de mai jos:

float real=5.6, *preal;
preal=&real;
*preal+=3;
printf("%f %d\n", real, sizeof(preal));

Sus
<<Pagina Materiale


Copyright © 2001-2002. Carmen Holotescu
All rights reserved. Published by Timsoft