Showing posts with label pointer. Show all posts
Showing posts with label pointer. Show all posts

Wednesday, November 15, 2017

Expresii cu variabile pointer la referirea elementelor din masive

Dacă cineva vrea să folosescă în programe construcții omogene și în program să apară preponderent lucru cu variabile pointer, are mii de posibilități să facă acest lucru lejer, frumos și interesant.
Un programator va scrie secvența:
int x[100];
int i, n, s=0;
..............
for(i=0, i<n, i++) s+=x[i];
...............
dar tot at\t de bine, folosind faptul v[ v este de fapt un pointer spre o zonă de memorie de 100 de cuvinte alocate la definire, folosind variabila pointer v se va scrie:

for(i=0, i<n, i++) s+=*(x+i);
Aritmetica de pointeri arată că variabila i se incrementeaz[ cu lungimea unui cuvânt.
parantezele rotunde au prioritatea 1, deci ele se evaluează primele, ceea ce înseamnă că la adresa lui x se adună de i ori lungimea unui cuvânt, ceea ce duce la aflarea adresei elementului al i-lea din vector. Operatorul de referire are prioritatea 2 ceea ce înseamnă că se execută după evaluarea expresiei din paranteze. Deci referirea înseamnă extragerea conținutului din zona de memorie a cărei adresă a fost calculată.
Dacă se lucrează cu masive bidimensionale lucrurile stau tot așa, ceea ce permite și o generalizare.
int xx[17][12];
int i, j, n=9, m=11, s=0;
..............
for(i=0, i<n, i++) 
for(j=0, i<m, i++) s+=xx[i][j];
...............
Masivul bidimensional xx este de fapt o variabilă pointer spre pointer, adică are dpuă niveluri de indirectare. În loc de xx[i][j] se va scrie *(*(xx+i)+j) și aplicând regulile de de parcurgere de la stânga spre dreapta și restricțiile de la aritmetica de pointeri se va obține adresa elementului xx[i][j]. Se știe că xx+i înseamnă că la adresa lui xx se adaugă 12 de înmulțit cu lungimea cuvântului, așa cum este definită variabila de tip întreg. Se obține adrea de început a liniei i din matrice. Apoi se adaugă deplasarea elementului j și primul * din partea stângă ca permite referitea elementului de la acea adresă, adică a elementului xx[i][j], cum cere algoritmul de evaluare a sumei elementelor unei matrice. Pentru un masiv tridimensional definit prin:
int yy[17][12][18];
referirea elementului yy[i][j][k] se va realiza folosind variabila pointer yy care are trei niveluri de indirectare cu expfresia:
*(*(*((yy+i)+j)+k). 
.......
for(i=0, i<n, i++) 
for(j=0, i<m, i++) s+=*(*(*((yy+i)+j)+k);
Frumos, nu?
Lucrul cu aceste expresii este perfect în momentul în care are loc alocarea dinamică a masivelor uni, bi și tridimensionale, ceea ce dă o mare șansă programatorilor de a ameliora gradul de ocupare al zonelor de memorie.

(15 noiembrie 2017)

Tuesday, November 14, 2017

Lucru cu variabile pointer

Istoria informaticii românești ar comite o mare greșeală dacră ar consemna faptul că variabilele pointer au venit în programare să zicem cu limbajul PASCAL sau cu limbajul C. S-a lucrat cu variabile pointer masiv în limbajele de asamblare, căci mai toate limbajele de asamblare au avut modul de adresare indirectă și posibilitatea de a încărca în diferite zone de memorie deplasări ale variabilelor, așa-zisele adrese chiar la definirea de variabile. Ceea ce se numește acum aritmetica pointerilor, exista și în programarea în limbaje de asamblare, numai că programatorii erau obligați să respecte regulile pentru a face referiri corecte de variabile, știută fiind obligativitatea ca adresele operanzilor să fie niște numere divizibile prin niște constante, funcție de tipul operației care se executa, căci una este să lucrezi cu operanzi pe 2 baiți, alta este ca operandul să fie definit pe 4 baiți și tot așa.
Definirea și referirea variabilelor pointer elementare se realizează prin instrucțiunile de forma:
tip_variabilă_elementară  *nume_variabilă_pointer, nume variabilă_elementară;
........................
nume_variabilă_pointer=&nume variabilă_elementară;
......................................
*nume_variabilă_pointer=valoare;
...............................
Exemplu:
#include <stdio.h>

void main()
{
    int *pa, *pb, *pc, *pe, a=5, b=7, c=12, e;
    pa=&a;
    pb=&b;
    pc=&c;
    pe=&e;
   *pe=*pa+*pb+*pc;
    printf("e = %d",*pe);
}
Programatorul are la dispoziție posibilitatea de a defini variabile pointer și de a le inițializa la definire prin construcții de forma:
int a=5, b=7, c=12, e, *pa=&a, *pb=&b, *pc=&c, *pe=&e ;
Dacă nu s-ar lucra cu variabile pointeri exemplud de mai sus ar arăta astfel:
void main()
{
    int  a=5, b=7, c-12, e;
    e=a+b+c;
   printf("e = %d",e);
}
ceea ce este cu mult mai simplu. Numai că rolul variabilelor pointer este să permită evaluarea unei aceleiași expresii cu alți operanzi și scrierea să fie în forme cu mult mai concentrate.
void main()
{
    int *pa, *pb, *pc, *pe, a=5, b=7, c=12, e;
    int *px, *py, *pz, *pw, x=5, y=7, z=12, w;
    pa=&a; px=&x;
    pb=&b; py=&y;
    pc=&c; px=&z;
    pe=&e;pw=&w;
   *pe=*pa+*pb+*pc;
   *pw=*px+*py+*pz;
    printf("e = %d",*pe);
    printf("w = %d",*pw);
}
Cei ce au venit din programarea în limbaj de asamblare au înțeles marile avantaje oferite de variabilele pointer mai ales atunci când lucrează cu proceduri și trebuie să returneze nu o singură valoare. Ei concentrează acea mulțime de rezultate ce trebuie returnate într-o variabilă agregată și procedura returnează un rezultat care este de fapt o variabilă pointer. Deci inseamnă că funcția returnează un ponter spre un vector sau spre o matrice sau returnează un pointer spre o variabilă de tip struct.
Funcția care inițializează un vector cu date de la tastatură este:
int *initvector (int n).
{
int v[100], i;
for(i=0; i<n; i++)
   {
    printf("componenta  v[ %d] ",i);
    scanf("%d ",&v[i]);
    }
    return (v);
}
O funcție care returnează și valoarea lui n dar și vectorul va impune definirea unei variavile de structură:
struct alfa {
                 int n;
                 int v[100];
                 }, *palfa;
Pentru a simplifica lucrurile cu typedef se definește un tip beta de dată struct și apoi se face fix orice cu el, inclusiv se impune ca funcția să returneze un pointer spre o variabilă pointer de acel tip structurat.
* beta initvector()
          {
           beta *prezult;
           ............
           return (rezult);
           }

(15 noiembrie 2017)