11.07.2015 Views

prog2 c4 - Alas

prog2 c4 - Alas

prog2 c4 - Alas

SHOW MORE
SHOW LESS
  • No tags were found...

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

Programiranje 2 - 05PokazivačiD. VitasReferenciranje idereferenciranje• Operator referenciranja: &Operator dereferenciranja: *• Ako je x promenljiva tipa T, tada sa &xobeležavamo adresu promenljive x i to je izraztipa T *.• Ako je promenljiva p tipa T *, onda *p je izraztipa T. Promeljiva p se naziva pokazivač. To jepromenljiva čija je vrednost adresa.PrimerNeka je celobrojna promenljiva x na adresi1234 i neka je njena vrednost 22.(int x = 22;) i neka je p: int *p; Tada:• iskaz p = &x;znači da je vrednost p adresa od x, tj.p je 1234 (adresa od x).• vrednost izraza *p je 22 (vrednost x).Pokazivač na pokazivačPokazivački tip/* PTR.C: Pokazuje pokazivac na pokazivac. */#include main()int val = 1234; // vrednostint *ptr = &val; // pokazivac na vrednost: adresa valint **ptr_ptr = &ptr; // pokazivac na pokazivac : adresa// ptr u kojoj je adresa valprintf("Adrese val = %p ptr = %p ptr_ptr = %p\n", &val, ptr, *ptr_ptr );printf( "val = %d %d %d\n", val, * ptr, **ptr_ptr );getchar();}ptr.exepokazivač = adresa nekog objektaodređenog tipa• Opis tip * identifikator• Kompatibilan sa adresnim operatorom &• Deklaracijachar x, *p; ...p = &x; *p = 'a'; ...1


Pokazivački tipUvođenje preko typedef, npr.typedef char * tip_p_char;typedef enum{C,Z,P} * tip_p_boja;typedef osoba * tip_p_osoba;Pokazivački tiposoba nik; // struktura osoba i promenljiva nikosoba * pok_osoba; // pok. na strukt. osoba// Sinonim za tip osoba *typedef osoba * tip_p_osoba;// Deklaracija pok. na// strukturu osoba niktip_p_osoba p_nik;Strukture• Pokazivač na strukturuEkvivalentne notacije za struct nesto *p;(*p).s = ...p->s = ...Pokazivački tip• Definicija pokazivača "zahvata" u memorijiprostor koji je dovoljan da se u njemunađe jedna adresa• Kompilator (???) kontroliše tip pokazivača(koji definiše korisnik:objekat = jedna adresa i jedna sekvencijabitova koja se interpretira na osnovu tipa!)Pokazivački tipPokazivač može da pokazuje na bilo koji tip:- na ugrađeni (char, int, float,...)- na strukture, unije, enum- na nizove i niske- na pokazivače- na funkcijePokazivački tip void *Tip void * je tip univerzalnog pokazivača.Ovaj tip ne specifikuje prirodu objekta na kojipokazuje --> aritmetičke operacije suneprimenljive na void *.Primena: int funk( void * );sizeof( void * ) je obično sizeof( int).2


Pokazivački tipKompatibilnost pokazivačkog tipa:• Pokazivači su saglasni među sobom i sacelobrojnim tipom (posredstvom koercije, ili cast:(tip) izraz)• Koercija je obavezna (u ANSI C-u) osim za tipvoid *• NULL ( (void *) 0) je adresa nula def. u, zajednička za sve tipove pokazivačaPokazivači i argumenti Pokazivači dopuštaju prenos argumenatafunkciji po referenci (adresa). Na ovaj način se prenose nizovi. Prenos po referenci omogućava dafunkcija radi neposredno nadargumentima. Promenljiva nizovskog tipa je konstantnipokazivač na osnovni tip niza.Pokazivačka aritmetikaAritmetika pokazivača je definisana tako dabude saglasna sa nizovima.Primer. Xtip *p;int i;Xtip *t[100];1. Dozvoljeni aditivni operatori:pokazivač+/-intnpr. p+i je tipa XtipPokazivačka aritmetika2. Saglasnost sa nizovima:t[i] se izračunava kao *(t + i)(dozvoljeno je i p[i] i *(p + i))Ako p pokazuje na t[k],onda p+i pokazuje na t[k+i]Pokazivačka aritmetika3. Operatori ++ i -- se primenjuju napokazivače, ali ne na nizove (jer su tokonstantni pokazivači)!!!++p pokazuje na sledeći objekt tipa Xtip,odn.++p ima vrednost(size_t) p + sizeof(Xtip)Pokazivačka aritmetika4. Razlika pokazivača istog tipa je brojobjekata između te dve adrese(p+i) - p je i(i je tipa označeni ceo broj i definisan u)Posebno, &t[i+1] - &t[i] je 1.3


Kopiranje niza 1int s[DIM], t[DIM];............................void cpy1( int s[], int t[] ) {int i;for( i = 0; i < DIM; i++ )t[i] = s[i];}Kopiranje niza 2int s[DIM], t[DIM];............................void cpy2( int *s, int *t ) {int i;for( i = 0; i < DIM; i++ )*t++ = *s++;}Razlika cpy1 i cpy2U funkcij cpy2 nizovi s i t su lokalnepromenljive pokazivačkog tipa, pa su izrazis++ i t++ dozvoljeni!!!s++ i t++ su nedozvoljeni nad globalnimpromenljivim koje su nizovi!!!Pokazivački tip• U opisu argumenata funkcijeTIP *t je ekvivalentno sa TIP t[]• Poređenje pokazivača (==, !=)– p != q, p == 0– (p) ima vrednost tačno za ( p != NULL )– (!p) ima vrednost tačno za (p == NULL)• *p++ = i je ekvivalentno sa *p = i; p=p+1;• Zabranjeno: unarno -, *, /, %, bitovski op.ZadatakData je vrednost X i niz A. sastaviti deo programa kojieliminiše X iz niza uz "sleganje" ostatka niza (test2)./*Deklaracije */int A[50]; /* niz */int N; /* dimenzija niza */int X; /* vrednost koja se izbacuje */int *P1, *P2; /* pomoćni pokazivači *//* Unos */printf("Dimenzija niza (max.50) : ");scanf("%d", &N );for (P1=A; P1


Zadatak/* Brisanje svih pojavljivanja X i kompresija:* Kopiramo elemente iz P1 ka P2 i uvećavamo P2* za sve elemente koji su različiti od X */for (P1=P2=A; P1


Idejaint lin_pretraga( int kljuc) {int i;algoritam nefor( i = 0; i < N; i++ ) zavisi od:if( a[i].k == kljuc ) return i;return -1;}Idejaint lin_pretraga( ??? ) {int i;for( i = 0; i < ??? ; i++ )if( f( a[i].k, kljuc ) ) return i;return -1;}bsearch~ kao:void *bsearch(const void *key,const void *base,size_t n,size_t size,int (*cmp)(const void *keyval,const void *datum))// ključ - pokazivač na tip// niz base u rastućem// poretku// dimenzije n// dužina tipa// funkcija za poređenje// vrednost ključa// podatak za poređenjeint lin_pretraga( (int) kljuc ) {int i;for( i = 0; i < sizeof(a)/sizeof(a[0]) ; i++ )if( (* f) ( a[i].k, kljuc ) ) return i;return -1;}RekurzijaRekurzijaKažemo da je neki objekat rekurzivan akose definiše na osnovu vlastite definicije.Primer:- rečnik (definiciona literatura)- TV na TV (Wirth)- matematičke definicije6


Rekurzija... kao sredstvo definisanja u matematici...Primer 1. Skup N prirodnih broojeva definiše se rekurzivnona osnovu sledećih pravila:(a) 1 je prirodan broj(b) ako je n prirodan broj, onda je i n+1 prirodan brojKonstruišemo N na sledeći način: prema (a), 1 je u N.Prema (b), tada je i 1+1 u N,i 1+1+1 je u N,...RekurzijaPrimer 2. Faktorijel definišemo sledećim pravilima:(a) 0! = 1(b) n! = n * (n-1)!ili:(a) F(0) = 1(b) F(n) = n * F(n-1)Npr.F(3) = 3*F(2) = 3*2*F(1) = 3*2*1*F(0) = 3*2*1*1RekurzijaU matematici: mogućnost definisanjabeskonačnog skupa objekata konačnimsredstvimaU programiranju:(a) matematička definicija problema jedata rekurzivno (npr. n!)(b) definisana je samo konačna klasaobjekata!!!RekurzijaSredstva kojima se implementira rekurzija:(a) funkcija (koja poziva samu sebe)(b) rekurzivne strukture podataka (ili još,dinamičke strukture, koje se definišupozivom na same sebe)Rekurzivne funkcijeDirektna rekurzija:r(...) {............r( ... );............ } Primer. n!Indirektna (posredna) rekurzija, npr.r(...) { ............; s( ... ); ............ }s(...) { ............; r( ... ); ............ }Primer. E-->(E) | brojRekurzivne funkcijeImplementacija rekurzije ... povezana saupotrebom unutrašnje memorije, pa jerekurzija u programiranju ograničenaveličinom memorije i ne predstavlja uvekpodesan način za implementiranjerešenja.Svaki rekurzivni program se može svesti naiterativni (Knuth).7


PrimerLogaritamska redukcijaData su dva cela broja A, B ( => 0 ). Izračunati A*B.MNO1: a = A; b = B; z = 0;while( b > 0 ) {z = z + a;b = b - 1; }U petlji važi invarijanta:z + a*b = A*Bprimer41.cMNO2: a = A; b = B; z = 0;while( b > 0 ) {if( nepar(b) ) {z = z + a;a = a*2;b = b / 2; }}primer42.cRekurzivna definicijaMNO3(a) b = 0 ⇒ z = 0(b1) b != 0 ⇒ z = m(a*2, b/2) ako par(b)(b2) b != 0 ⇒ z = m(a*2, b/2) + aako nepar(b)Odavde se izvodi rekurzivna funkcija za množenje.primer43.cint mnozenje( int x, int y ) { // x = A, y = Bint r;if( y == 0 ) return 0;if( par( y ) == 0 )r = mnozenje( 2*x, y/2 );else { r = mnozenje( 2*x, y/2 );r = r + x; }return r;}Izvršavanje MNO3int mnozenje( int x, int y ) {int r;if( y == 0 ) return 0;if( par( y ) == 0 )r = mnozenje( 2*x, y/2 );else {r = mnozenje( 2*x, y/2 );r = r + x; }return r;}poziv r = m( 5, 3)x1 = 5, y1 = 3; par(y1) = 0---> r1 = m( 10, 1 )x2 = 10, y2 = 1, par(y2) = 0---> r2 = m( 20, 0 )x3 = 20, y3 = 0 --> return 0r2 = 0 + x2 --> r2 = 10 --> return 10r1 = 10 + x1 --> r1 = 15 --> return 15r = 15Drvo pozivam(5,3)x1 = 5 m(10,1) r = r +x1x2 = 10 m(20,0) r = r +x2r = 08


Drvo pozivaIzvršavanje se svodi na "listove":x1 = 5;x2 = 10;r = 0;r = r + x2;r = r + x1; ----> r = 15Alokacija memorijeKlase alokacijezona teksta(tekst programa)zona podataka(globalne promenljive)zona steka(privremeni podaci, lokalne promenljive)zona heap-a(dinamička memorija)Klase alokacije promenljivihPromenljiva se može nalaziti u različitimzonama alokacije:• statička promenljiva: zona podataka• automatska promenljiva: zona steka• dinamička promenljiva: promenljiva uheap-u kojoj je prostor dodeljen na zahtev(pokazivači)Predefinisana alokacijaAlokacijaalokacijatrajanjeinicijalizacijaglobalnapromenljivastatička(u kompilaciji)tokom celogprogramana 0lokalnapromenljivaautomatska(aktiviranjem bloka)tokom izvršavanjablokanema• ključna reč static omogućava da lokalna promenljivazadrži vrednost između dva ulaska u blok u kome jedefinisana:Npr. int primer(){static int n = 0;return n++; }• ključna reč register nalaže da se automatskojpromenljivoj dodeli, ako je moguće, mašinski registar (začesto korišćenu promenljivu; adresa (&) nije dostupna):Npr. for( i = 0; i < N; i++ ) {register int temp;temp = i; ... }9


Implementacija pozivafunkcijeSvaki poziv neke funkcije zauzima novi prostor u memorijikoji je rezervisan za taj poziv i koji je oblika:povratna vrednost (120)vrednost parametara (5)povratna adresa (gde nastaviti?)lokalne promenljive funkcije (f)Taj prostor se naziva aktivacioni slog. Kada se izvršavanjefunkcije okonča, ovaj prostor se oslobađa - vrednostikoje su bile u njemu tokom izvršavanja funkcije se gube.poziv r = m(5, 3)Povratak na MNO3povratna vrednost (?)vrednost parametara (5, 3)povratna adresa (gde nastaviti?)lokalne promenljive funkcije (r)Formira se na steku prostor za x 5y 3r ?Posle poziva m(10, 1)poziv r = m(10, 1)povratna vrednost (?)vrednost parametara (10, 1)povratna adresa (gde nastaviti?)lokalne promenljive funkcije (r)Formira se na steku prostor za x 10y 1r ?x 5y 3r ?Posle poziva m(20, 0)Na steku je prostor za x 20y 0r 0x 10y 1r ?x 5y 3r ?Nema daljih poziva funkcije m --> return 0;Posle izlaza iz m(20, 0)Na steku je prostor zaPosle izlaza iz m(10, 1)Na steku je prostor zax 10y 1r 0x 5y 3r ?x 5y 3r 1010


Posle izlaza iz m(5, 3)Primer 2 - n!Na steku ostaje prostor zaprimer46.cr 15Prostor koji su zauzimale promenljive x1, y1,x2, ... više nije dostupan.int factoriel( int n ){if( n == 0 ) return 1;else return n * factoriel( n - 1 );}Izračunavanje n!factoriel( 3 )Izračunavanje n!Prednost iterativne verzije:3 * factoriel( 2 )2 * factoriel( 1 )1 * factoriel(0)1int fact( int n ) {int m = 1;while( n > 0 ) m *= n--;return m; }Nije potreban dodatni prostor!!!Fibonačijev nizint Fibonaci( int n ) { // primer44.cif( n


Repna rekurzijaKada se rekurzivni poziv izvršava kao poslednjiiskaz u funkciji, onda takav poziv nazivamorepna (terminalna, završna) rekurzija (engl. tail).Npr.int mnozenje( int x, int y ) {// x = A, y = Bint r;repna rekurzijaif( y == 0 ) return 0;if( par( y ) == 0 ) r = mnozenje( 2*x, y/2 );else { r = mnozenje( 2*x, y/2 ); r = r + x; }return r; }nije repna rekurzijaEliminacija repne rekurzijefunk( x ) {if( C ) { I; return y; }else { J; return funk( z ); }se odstranjuje sledećom transformacijom:funk( x ) {while( ! C ) { J; x = z ; }{ I; return y; }}repna rekurzijaOva transformacija ubrzava program (~ 30%).Primer MNO3n!int mnozenje( int x, int y ) {/* eliminacija repne rekurzije while-iskazom */while( (y == 0 ) && par( y ) ) { x = 2 * x; y = y/2; }}int fact_rep( int n, int m ) {if( n == 0 ) return m;/* Varijanta n! sa repnom rekurzijom */else return fact_rep( n-1, n * m );/* ostatak rekurzivne procedure */if( y == 0 ) return 0;else return mnozenje( 2*x, y/2 ) + x;}Eliminacija repne rekurzije daje iterativnu verziju:int fact_iter( int n, int m ) {while( n > 0 ) { m = n * m; n = n -1; }return( m ); }Dalji primeri rekurzije12

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!