curs7_an1_sem1_14_15

49
CURS 7 Pointeri 1

Upload: thehelper

Post on 12-Sep-2015

5 views

Category:

Documents


2 download

DESCRIPTION

Curs7_an1_sem1_14_15

TRANSCRIPT

  • CURS 7

    Pointeri 1

  • CUPRINS

    1. Noiuni introductive

    2. Operatori specifici pentru pointeri

    3. Operaii cu pointeri

    4. Apelul prin adres utiliznd pointeri

    5. Pointeri i referine

    6. Indirectarea multipl

    7. Pointeri constani i pointeri ctre constante

    8. Tablouri i pointeri

    9. Funcii pentru lucrul cu iruri de caractere

    10. Pointeri spre funcii

    11. Transferarea de argumente ctre funcia main( )

    12. Alocarea dinamic a memoriei

    13. Funcii pentru manipularea zonelor de memorie 2

  • 1. NOIUNI INTRODUCTIVE

    Tipul pointer (indicator) reprezint adresa unei locaii de memorie

    adresele sunt valori numerice ntregi fr semn

    Tipuri de pointeri:

    pointeri de date:

    conin adresa unor variabile sau constante din memorie

    pointeri de funcii: conin adresa codului executabil din funcii

    pointeri de obiecte:

    conin adresa unui obiect

    pointeri generici sau pointeri void:

    conin adresa unui obiect oarecare 3

  • NOIUNI INTRODUCTIVE

    Pointerii de date se declar astfel:

    tip *nume_pointer;

    Pointerii generici se declar astfel:

    void *nume_pointer;

    Exemplu:

    int *nptr;

    float *a, rezultat;

    int *tabptr[10];

    void *pgen;

    4

  • 2. OPERATORI SPECIFICI PENTRU POINTERI

    Operatorul & (adresare sau refereniere):

    permite aflarea adresei unei variabile oarecare:

    &nume_var

    rezultatul este un pointer la tipul variabilei

    Operatorul * (indirectare sau derefereniere):

    se folosete pentru a afla ce se gsete la o adres:

    *nume_pointer ... la adresa nume_pointer ...

    5

  • OPERATORI SPECIFICI PENTRU POINTERI

    expresia *nume_pointer poate fi folosit att pentru a obine valoarea obiectului ct i pentru 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:

    int *p;

    ...

    *p = 10; // eroare, pentru ca lui p nu i s-a asignat o valoare

    6

  • OPERATORI SPECIFICI PENTRU POINTERI

    Exemplu:

    void main(void)

    {

    int i=10, *ptri;

    ptri = &i;

    printf("Valoare var : %d \nLa adresa var : %d" , i, *ptri);

    *ptri = 20;

    printf("Valoare var : %d \nLa adresa var : %d" , i, *ptri);

    }

    7

  • OPERATORI SPECIFICI PENTRU POINTERI

    In C/C++ se permite ca orice tip de pointer s pointeze oriunde n memorie, tipul pointerului determinnd modul n care va fi tratat obiectul pointat:

    Un pointer de un anumit tip nu va fi folosit s pointeze o dat de alt tip:

    int q;

    double *dp;

    dp = &q;

    *dp = 20.5;//voi scrie 8 octei

    8

  • OPERATORI SPECIFICI PENTRU POINTERI

    sau

    int *p;

    double q, temp;

    temp=20.5;

    p=&temp;

    q=*p; //iau doar cat e specific unui int

    printf (\nprin pointer int luat de la un double: %lf,q);

    9

  • OPERATORI SPECIFICI PENTRU POINTERI

    Pointerii generici (void *) nu sunt asociai unui anumit tip de date:

    dimensiunea zonei de memorie adresate i interpretarea datelor din acea zon nu sunt definite

    Aceti pointeri pot fi utilizai cu mai multe tipuri de date, ns numai cu operatorul de conversie explicit (cast):

    10

  • OPERATORI SPECIFICI PENTRU POINTERI

    int x;

    float y;

    void *p;

    ...

    p=&x; // lui p i se atribuie adresa de memorie

    unde pot fi intregi

    *(int*)p = 10;

    p=&y; // lui p i se atribuie adresa de memorie

    unde pot fi flotanti

    *(float *)p = 20.5;

    11

  • OPERATORI SPECIFICI PENTRU POINTERI

    Operatorul cast poate modifica semnificaia pointerilor:

    int *pi;

    float *pf;

    ...

    *((char*)pf) -> primul octet al unei variabile de tip float

    *((char*)pf+1) -> al doilea octet al unei variabile de tip float

    Construcia (char*) este folosit pentru accesul pe octet la zone de memorie de mrimi diferite

    12

  • 3. OPERAII CU POINTERI

    Cu ajutorul pointerilor se pot efectua operaii de:

    atribuire

    comparare

    adunare

    scdere

    incrementare

    decrementare

    In operaii se ine cont de faptul c adresele care reprezint pointerii au valori numerice ntregi fr semn

    13

  • OPERAII CU POINTERI Atribuirea

    Dac:

    tip1 *id_ptr1;

    tip2 *id_ptr2;

    id_ptr1 = id_ptr2;

    Avem urmtoarele cazuri:

    tip1 este void, atunci tip2 poate fi oarecare

    tip2 este void, atunci tip1 poate fi oarecare (la

    asignare se foloseste cast)

    tip1 si tip2 sunt identice, atribuirea este corect

    tip1 si tip2 difer, atunci compilatorul genereaz un avertisment sau o eroare 14

  • OPERAII CU POINTERI

    #include

    using namespace std;

    #include

    void main(){

    void *pg;

    int *pi;

    double *pd;

    int nota=10;

    double media=9.97;

    pi=&nota;

    pg=pi;

    cout

  • OPERAII CU POINTERI

    pd=&media;

    pg=pd;

    cout

  • OPERAII CU POINTERI Compararea a doi pointeri

    Se face cu operatorii relaionali, dar numai n cazul n care pointerii pointeaz pe obiecte de acelai tip

    Exemplu:

    int *p1, *p2, i, j;

    ...

    p1=&i;

    p2=&j;

    if (p1 < p2)

    printf ("p1= %n p2 = %n\n", p1, p2);

    17

  • OPERAII CU POINTERI

    Operatorii == i != pot fi folosii pentru a compara pointeri cu o constant special NULL definit de obicei n stdio.h prin:

    #define NULL 0

    Pentru un pointer generic (void *p) se pot face comparaiile:

    p == NULL i p != NULL

    In C++ este recomandabil a folosi:

    if (p == 0) if (!p)

    if (p != 0) if (p)

    18

  • OPERAII CU POINTERI

    Adunare, scdere i incrementare, decrementare

    Pot fi adugate sau sczute doar cantiti ntregi

    Operaiile se efectueaz relativ la tipul pointerului (int, float, char, etc.)

    Fie declaraia: tip *id_ptr;

    Operaiile: id_ptr + n, id_ptr - n

    corespund adugrii/scderii la adresa obinut n cadrul variabilei id_ptr a valorii: n * sizeof(tip)

    19

  • OPERAII CU POINTERI

    Analog se efectueaz i operaiile de incrementare/decrementare doar c n este= 1/-1

    Rezultatul este corect doar atunci cnd pointerul adreseaz un tablou i prin opearatia aritmetic se produce o deplasare n interiorul limitelor tabloului

    20

  • OPERAII CU POINTERI Exemplu:

    float *fp1, *fp2, tf[10]; // sizeof (float) = 4

    double *dp, td[10[; // sizeof (double) = 8

    ...

    fp1 = &tf[0]; //tf

    dp = &td[9]; // adresa celui de-al 10-lea element

    fp2 = fp1+5; // fp2 va contine : adresa lui tf + 5*4

    dp = dp-2; // dp va contine : adresa lui dp - 2*8

    fp1++; // fp1 va contine : adresa lui fp1 + 1*4

    dp--; // dp va contine : adresa lui dp - 1*8

    21

  • OPERAII CU POINTERI

    Operaia de incrementare/decrementare se poate aplica:

    asupra pointerului nsui

    asupra obiectului pe care l pointeaz

    Dac se folosete varianta:

    int *p, q=17, v;

    p=&q;

    v=*p++; // nti se aplica * i apoi ++ asupra pointerului

    Dac se folosete varianta:

    v = (*p)++; // se obine nti coninutul de la adresa p

    // care apoi se incrementeaz cu 1

    22

  • OPERAII CU POINTERI

    . (programul de la slide-ul 15)

    res=(*pd)++;

    cout

  • OPERAII CU POINTERI

    #include

    using namespace std;

    #include

    void main(){

    int l=1, j=5,k, *p;

    p=&l;

    *p=2;//modific l, operatie asupra continut

    cout

  • OPERAII CU POINTERI

    p=&l;

    cout

  • 26

  • OPERAII CU POINTERI

    Scderea a doi pointeri

    Este permis numai pentru pointeri de acelai tip ce refer un tablou, rezultatul fiind o valoare care reprezint diferena de adrese divizat la dimensiunea tipului de baz

    Adunarea pointerilor nu este permis !

    Exemplu:

    float l,ft[9];

    float *p1=&ft[4], *p2=&ft[2];

    ...

    l = p2-p1; // l = (adresa p2- adresa p1)/4

    Datorit rolului tipului la adunare i scdere, operanzii nu pot fi pointeri void sau pointeri spre

    funcii 27

  • 4. APELUL PRIN ADRES UTILIZND POINTERI

    Transferul parametrilor prin valoare (implicit):

    const n ncrcarea valorii parametrilor efectivi n zona de memorie a parametrilor formali

    dac parametrul efectiv este o variabil, orice operaie efectuat n funcie asupra parametrului formal nu afecteaz variabila

    spunem c se lucreaz cu copii ale parametrilor efectivi

    Dac vrem ca o funcie s modifice o variabil parametru efectiv, atunci trebuie s transmitem funciei, la apel, adresa variabilei:

    ca i parametri formali se pot folosi pointeri unde se vor copia aceste adrese

    28

  • APELUL PRIN ADRES UTILIZND POINTERI

    void schimba1(int a, int b)

    {

    int temp;

    temp=a;

    a=b;

    b=temp;

    }

    Apel:

    schimba1(x, y);

    29

    void schimba2(int *a, int *b)

    {

    int temp;

    temp=*a;

    *a=*b;

    *b=temp;

    }

    Apelul:

    schimba2(&x, &y);

  • APELUL PRIN ADRES UTILIZND POINTERI

    Dac la apelul unei funcii se folosete ca i argument un tablou, funcia va primi doar adresa acelui tablou, adic adresa primului element din tablou

    Variante:

    parametrul formal este declarat ca un tablou fr dimensiune

    int cauta(int p[ ], int n, int x );

    parametrul formal este declarat ca un pointer ctre tipul tabloului, argumentul folosit ca i parametru efectiv fiind adresa tabloului asupra cruia se fac operaii n funcie

    int cauta(int *p, int n, int x ); 30

  • APELUL PRIN ADRES UTILIZND POINTERI

    // cautare pe un tablou

    int cauta(int *p, int n, int x );

    int cauta(int *p, int n, int x)

    {

    int i;

    for(i=0; i

  • 5. POINTERI I REFERINE

    Referinele, ca i pointerii, conin adrese de memorie

    Se declar cu ajutorul operatorului de adresare ("&) i se iniializeaz obligatoriu la inceput cu o adres (a unei variabile sau a unei constante), fiind un alias al

    ei:

    int i;

    int &r = i; //alias

    32

  • POINTERI I REFERINE

    Accesul la o variabil prin intermediul unei referine se face simplu fr a mai folosi operatorul de indirectare ca n cazul pointerilor:

    int i; int i;

    int *p; int &r = i;

    ...

    p = &i;

    *p = 100; // i = 100 r = 1000; // i = 1000

    33

  • POINTERI I REFERINE

    Diferene ntre pointeri i referine:

    dup modul de declarare:

    * pentru pointeri

    & pentru referine

    dup modul de utilizare:

    pointerii:

    se asociaz unei variabile cu operatorul &, pentru accesul la valoare se utilizeaz operatorul *

    pot fi asociai mai multor variabile la momente diferite de timp i deci pot conine adrese diferite

    referinele:

    se asociaz unei variabile i numai uneia la definire

    conin tot timpul adresa aceleiai variabile fiind de fapt o redenumire (alias) a variabilei

    li se asociaz valori pe baza unei atribuiri simple 34

  • POINTERI I REFERINE

    Restricii:

    nu sunt permise referine la referine, pointeri la referine, referine la cmpuri de bii, tablouri de referine, dar putem avea referine la pointeri

    o referin nu poate avea valoarea NULL

    o referin nu poate fi asociat unei alte variabile

    Utilizare:

    se folosesc rar variabile referine simple

    uzual se folosesc la transmiterea parametrilor prin

    referin, caz n care indirectarea este ascuns i nu este necesar dereferenierea n funcie (utilizarea operatorului *) 35

  • POINTERI I REFERINE

    // varianta cu pointeri

    void schimba2(int *a, int *b)

    {

    int temp;

    temp = *a;

    *a = *b;

    *b = temp;

    }

    apelul :

    schimba2(&i, &j);

    36

    // varianta cu referine

    void schimba3(int &a, int &b)

    {

    int temp;

    temp = a;

    a = b;

    b = temp;

    }

    apelul :

    schimba3(i, j);

  • POINTERI I REFERINE

    Rezultatul unei funcii se poate transfera prin referin astfel:

    int& func(...)

    {

    static int var;

    ...

    return (&var);

    }

    Trebuie evitat returnarea adresei (prin pointer sau referin) unui obiect automatic, obiect care se distruge la ieirea din funcie

    37

  • 6. INDIRECTAREA MULTIPL

    Cnd un pointer pointeaz alt pointer avem un proces de indirectare multipl:

    Pointer ctre pointer -----> Pointer -----> Obiect

    Primul pointer conine adresa celui de-al doilea pointer, pointer care pointeaz locaia care va conine obiectul,...

    Declararea se face utiliznd un asterisc suplimentar n faa numelui pointerului:

    char **pm, *p, ch;

    ...

    p = &ch;

    pm = &p;

    **pm = 'A'; // lui ch i s-a asignat valoarea A

    prin 2 pointeri 38

  • 7. POINTERI CONSTANI I POINTERI CTRE CONSTANTE

    Exist pointeri ctre constante i pointeri constani (care nu pot fi modificai):

    pointeri ctre constante

    const char *str1 = "pointer catre constanta";

    //str1[0] = 'P'; // incorect

    str1 = "ptr la const"; // ok

    pointeri constani

    char *const str2 = "pointer constant ";

    //str2 = "ptr const"; // incorect

    str2[0] = 'P'; // ok

    39

  • POINTERI CONSTANI I POINTERI CTRE CONSTANTE

    pointeri constani ctre constante

    const char *const str3 = "pointer constant la constanta";

    //str3 = "ptr const la const"; // incorect

    //str3[0] = 'C'; // incorect

    un pointer poate, indirect, modifica totui o variabil declarat cu modificatorul const astfel:

    *(tip *)&var;

    int const kk=7;//const int const kk=7;

    int k_var= *(int*)&kk; // val lui kk se depune in k_var

    cout

  • POINTERI CONSTANI I POINTERI CTRE CONSTANTE

    O funcie care are ca parametri formali pointeri, dar nu are voie s modifice datele pointate de parametru efectiv arat astfel:

    void cifru(const char *src, char *dest)

    {

    while(*src)

    {

    *dest = *src + 5;

    dest++;

    src++;

    }

    } 41

  • ALTE CONSIDERAII REFERITOARE LA POINTERI

    In limbajul C/C++ se folosesc des funcii care returneaz pointeri

    Exemplu:

    char *strcpy(char *dest, const char *src);

    Astfel de funcii se mai folosesc i pentru alocarea dinamic a memoriei, prelucrarea listelor, arborilor, ...

    42

  • Exemplul 1:

    #include void 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 este: 0x%02x%02x%02x%02x\n", n, *((unsigned char *)pn+3), *((unsigned char *)pn+2), *((unsigned char *)pn+1), *((unsigned char *)pn));

    43

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

    scanf("%f", &r);

    pr = &r;

    printf("\nReprezentarea in memorie a lui %f este:

    0x%02x%02x%02x%02x\n", r,

    *((unsigned char *)pr+3),

    *((unsigned char *)pr+2),

    *((unsigned char *)pr+1),

    *((unsigned char *)pr));

    }

    44

  • Exemplul 2:

    #include void schimba1(int a, int b); void schimba2(int *a, int *b); void schimba3(int &a, int &b); void main(void) { int x, y; int *px, *py; int &rx=x, &ry=y; printf("\nIntroduceti valoarea lui x: "); scanf("%d", &x); printf("\nIntroduceti valoarea lui y: "); scanf("%d", &y); 45

  • schimba1(x, y);

    printf("\nNoile valori sunt: x = %d, y = %d", x, y);

    schimba2(&x, &y);

    printf("\nNoile valori sunt: x = %d, y = %d", x, y);

    schimba3(x, y);

    printf("\nNoile valori sunt: x = %d, y = %d\n", x, y);

    }

    46

  • void schimba1(int a, int b){

    int temp;

    temp=a;

    a=b;

    b=temp;

    }

    void schimba2(int *a, int *b){

    int temp;

    temp = *a;

    *a = *b;

    *b = temp;

    }

    void schimba3(int &a, int &b){

    int temp;

    temp = a;

    a = b;

    b = temp;

    }

    47

  • Exemplul 3:

    #include

    #include

    void main(void){

    int n, *p;

    int tab[ ] = {1, 3, 5, 7, 9};

    n = sizeof(tab)/sizeof(int);

    p = &tab[0];

    printf("\nElementele tabloului cu ++ de la inceput sunt: ");

    for(int i=0; i

  • p = &tab[0];

    printf("\nElementele tabloului de la inceput sunt: ");

    for(int i=0; i