P2 7 8 Dinamicka Alokacija Memorije

Embed Size (px)

Citation preview

  • Programiranje 2 2009 ETF Beograd 1/34

    P2: Sedma nedeljaPokazivai i dinamika alokacija

    memorije

    Programiranje 2 2009 ETF Beograd 2/34

    Zadatak 1 pokazivai (C55a) ta ispisuje sledei program?

    #include void main() {

    int a[]={1,0}, *p;p=a;printf("%d, ", *p++);printf("%d\n", *p);

    }

    Odgovori:A) 1, 2B) 1, 0C) 0, 0

    Programiranje 2 2009 ETF Beograd 3/34

    Pokazivai Pokaziva je promenljiva koja sadri adresu neke

    lokacije u operativnoj memoriji svi pokazivai imaju istu veliinu, u zavisnosti od veliine adresnog

    prostora na odgovarajuoj maini

    Definisanje pokazivaatip *ime;

    tip predstavlja tip podatka na koji se pokazuje (int, double) tip je potreban da bismo znali o kakvom se podatku radi prilikom

    pristupa podatku preko pokazivaa

    Adresa nekog podatka se pokazivau dodeljuje pomou adrsnog operatora &

    pa = &a; Lokaciji na koju pokaziva ukazuje se pristupa

    pomou operatora za indirektan pristup (dereferenciranje) *

    *pa = 1;Programiranje 2 2009 ETF Beograd 4/34

    Adresna aritmetika Dodela vrednosti

    pa = pb; Sabiranje i oduzimanje celobrojnog podatka

    jedinica mere pri sabiranju i oduzimanju pokazivaa sa celobrojnimpodatkom je veliina pokazivanog podatka!

    pa = pa + x; nova adresa pa e biti formirana kao zbir stare adrese pa i

    x*sizeof(pokazani_tip) Oduzimanje i uporeivanje dva pokazivaa

    binarni operator za oduzimanje i svi relacioni operatori ima smisla samo za pokazivae koji pokazuju na elemente istog niza

    Uporeivanje pokazivaa sa nulom konstanta 0 ili simbolika konstanta NULL iz

    #define NULL (0L) dodela vrednosti 0 ili NULL nekom pokazivau oznaava da pokaziva

    ne pokazuje ni na koji podatak

  • Programiranje 2 2009 ETF Beograd 5/34

    Pokazivai i nizovi Ako je definisan neki statiki niz:

    int a[] = {1,2,3,4}; Ime niza a predstavlja konstantni pokaziva na poetak niza!

    &a[0] a&a[i] a+ia[i] *(a+i)

    Zbog ove osobine, pokazivake promenljive se mogu tretirati kao nizovi mogue je koristiti operator za indeksiranje [], kao kod nizova

    a+3a+2a+1a+0a[3]a[2]a[1]a[0]4321a:

    Programiranje 2 2009 ETF Beograd 6/34

    Zadatak 1 - reenje Posmatramo deklaraciju:

    int a[]={1,0} a je niz celih brojeva, indeksira se od 0 duina niza nije eksplicitno zadata, ali se moe doznati iz broja inicijalizatora

    Dodela vrednostip=a;

    01a:

    01a:

    p

    Programiranje 2 2009 ETF Beograd 7/34

    Zadatak 1printf("%d, ", *p++);

    Prioritet operatora * i ++ je jednak, ali je asocijativnost ove grupe operatora sdesna ulevo

    Prema tome, prvo e se izvriti operator ++, ime se uveava vrednost pokazivaa i on pokazuje na naredni celobrojni podatak u memoriji

    Zbog osobine operatora ++, operator * e biti primenjen na staru adresu pokazivaa p i bie ispisana vrednost 1

    printf("%d\n", *p); Ispis: 1, 0 Odgovor: B

    01a:

    p

    Programiranje 2 2009 ETF Beograd 8/34

    Zadatak 2 pokazivai (C55b) ta ispisuje sledei program?

    #include void main() {

    int a[]={0, 1, 2, 3, 4};int i, *p;

    for (p=a, i=0; p

  • Programiranje 2 2009 ETF Beograd 9/34

    Zadata 2 reenjefor (p=a; p

  • Programiranje 2 2009 ETF Beograd 13/34

    Zadatak 3 reenje Programski jezik C automatski uzima u obzir

    veliinu pokazanog podatka prilikom primene operatora ++, --, +, - nad pokazivaima

    Veliina nekog podatka u memoriji, izraena u bajtovima, programskim putem moe da se odrediprimenom operatora sizeof(tip) ilisizeof(promenljiva)

    p++ p = p + sizeof(*p)

    Rezultat je : 1000 + 4 = 1004 Odgovor: C

    Programiranje 2 2009 ETF Beograd 14/34

    Zadatak 4 obrtanje niza (4.2) Napisati program na programskom jeziku C koji

    sa standardnog ulaza uitava niz celih brojeva, obre redosled brojeva u nizu i ispisuje niz redomod poetka.

    Algoritam: krenuti sa dva pokazivaa, od poetka i sa kraja zamenjivati mesta pokazanim elementima dok god se pokazivai ne

    sretnu

    43210a:

    p:q:

    Programiranje 2 2009 ETF Beograd 15/34

    Zadatak 4 - reenje Reenje ciklus sa izlaskom na sredini

    #include #define NMAX 100void main () {

    int a[NMAX], *p, *q, n;while (1) {printf ("n? "); scanf ("%d", &n);if (nNMAX) break;printf ("A? "); for (p=a; p

  • Programiranje 2 2009 ETF Beograd 17/34

    Dinamika alokacija memorije Prilikom definisanja skalarnih promenljivih ili

    nizova, memorija se zauzima statiki sve potrebe za memorijom moraju biti poznate unapred, pre

    prevoenja izvornog programa alocira se najee vie prostora nego to je potrebno prostor se zauzima u statikoj zoni memorije bilo kakva izmena kapaciteta zahteva ponovno prevoenje programa

    Reenje dinamika alokacija memorije radi se u vreme izvravanja programa broj i veliinu podataka ne moramo znati unpared memorija se alocira u dinamikoj zoni memorije (eng. heap) podacima u dinamikoj zoni memorije se pristupa preko pokazivaa ogranienje samo ukupan raspoloiv memorijski prostor u sistemu

    Odgovornost programera za ispravnu alokaciju i dealokaciju dinamike memorije!

    Programiranje 2 2009 ETF Beograd 18/34

    Manipulacija dinamikom memorijom (1) U C-u se za rad sa dinamikom memorijom koriste funkcije

    iz standardnog zaglavlja Zauzimanje dinamike memorije

    void* malloc(vel) vel predstavlja traenu veliinu memorije u bajtovima

    void* calloc(n,vel) n predstavlja broj elemenata niza vel predstavlja veliinu jednog elementa inicijalizuje zauzeti prostor nulama

    Obe funkcije vraaju generiki (void) pokaziva! ovakav pokaziva sadri samo adresu, a nije poznat tip podatka na koji ukazuje ne moe se dereferencirati, niti koristiti u adresnoj aritmeticij, osim poreenja ukoliko elimo da pristupimo memoriji preko njega, moramo izvriti eksplicitnu

    konverziju (cast) u neki tip

    Ukoliko je alokacija neuspena ove funkcije vraaju NULL

    Programiranje 2 2009 ETF Beograd 19/34

    Manipulacija dinamikom memorijom (2)

    Zauzeta memorija se obavezno mora osloboditifree(p)

    gde je p pokaziva koji sadri poetnu adresu bloka u memoriju koji je zauzet sa malloc, calloc ili realloc

    Promena veliine zauzetog prostoravoid* realloc(p, vel)

    menja veliinu dodeljene memorije na koju ukazuje pokaziva p na velbajtova

    bie detaljno objanjeno kasnije

    Programiranje 2 2009 ETF Beograd 20/34

    Zadatak 4 dinamiki nizovi Modifikovan da radi sa dinamikim nizovima

    #include #include

    void main () {int *a, *p, *q, n;printf ("n? "); scanf ("%d", &n);

    while (n>0) {a = calloc(n, sizeof(int));if (a == NULL) {

    printf("Neuspesna alokacija memorije!");exit(1);

    }

  • Programiranje 2 2009 ETF Beograd 21/34

    Zadatak 4printf ("A? "); for (p=a; p

  • Programiranje 2 2009 ETF Beograd 25/34

    Dinamike matrice (2) U C-u je mogue definisanje pokazivaa na neki

    drugi pokaziva, do proizvoljne "dubine" pokaziva na pokaziva na celobrojni podatak

    int **p; Prvi korak u stvaranju dinamike matrice je

    alokacija memorije za niz pokazivaa p = calloc(m, sizeof(int*));

    p je statiki alociran dvostruki pokaziva u koji e biti smetena adresa niza pokazivaa

    m je broj vrsta (redova) matrice svaki pokaziva u alociranom nizu pokazivaa e ukazivati na jedan niz

    elemenata koji e predstavljati vrste (redove) matrice p mora biti dvostruki pokaziva, jer da bi se pristupilo jednom elementu

    matrice (p[i][j]), mora se prvo odrediti adresa i-te vrste i pristupiti i-tom pokazivau u nizu pokazivaa, a zatim odrediti adresa j-tog elementa u nizu elemenata i pristupiti tom elementu

    p[i][j] *(*(p+i)+j)Programiranje 2 2009 ETF Beograd 26/34

    Dinamike matrice (3) Drugi korak u stvaranju dinamike matrice je

    alokacija vrsta matrice

    for (i=0; i

  • Programiranje 2 2009 ETF Beograd 29/34

    Zadatak 6 Izraz: *(*(a+i)+n-1-i));

    15

    11

    7

    3

    161413->a[3]

    12109->a[2]

    865->a[1]

    421->a[0]Za i = 3*(a + 3) a[3]

    *(*(a + 3) + 4 1 - 3) a[3][0]

    15

    11

    7

    3

    161413->a[3]

    12109->a[2]

    865->a[1]

    421->a[0]Za i = 1*(a + 1) a[1]

    *(*(a + 1) + 4 1 - 1) a[1][2]

    Ispisuje sadraj sporedne dijagonale matrice sleva-udesno (odozdo nagore)

    Odgovor: AProgramiranje 2 2009 ETF Beograd 30/34

    Zadatak 7 transponovanje (4.5) Sastaviti na jeziku C program za transponovanje

    pravougaone matrice celih brojeva. Matricu smestiti u dinamiku zonu memorije. Postupak ponavljati sve dok se za dimenzije matrice ne unesu nekorektne vrednosti.

    Transponovanje matrice: zamena mesta vrsta i kolona matrice prva vrsta postaje prva kolona, druga vrsta druga kolona itd...

    222

    444333

    111

    333

    421421421

    =>

    Programiranje 2 2009 ETF Beograd 31/34

    Zadatak 7 - reenje Reenje uz ouvanje originalne matrice

    #include #include void main () {int **a, **b, m, n, i, j;printf ("\nBroj vrsta i kolona? ");scanf ("%d%d", &m, &n);while (m>0 && n>0) {

    /* Stvaranje matrice i citanje elemenata matrice: */a = malloc (m*sizeof(int*));for (i=0; i

  • Programiranje 2 2009 ETF Beograd 33/34

    Zadatak 7 Reenje uz izmenu originalne matrice

    zadata matrica ne mora biti kvadratna mora se alocirati prostor kao za kvadratnu matricu cija je dimenzija jednaka

    vecoj dimenziji zadate matrice

    #include #include void main () {int **a, dim, m, n, i, j, t;/* Citanje dimenzija matrice: */printf ("\nBroj vrsta i kolona? ");scanf ("%d%d", &m, &n);while (m>0 && n>0) {

    dim = (m > n) ? m : n;

    Programiranje 2 2009 ETF Beograd 34/34

    Zadatak 7a = malloc (dim*sizeof(int*));for (i=0; i