Search
 
 
  Engleski
 
 
 
Open in this window (click to change)
Forum@DeGiorgi: Početna
Forum za podršku nastavi na PMF-MO
Login Registracija FAQ Smajlići Članstvo Pretražnik Forum@DeGiorgi: Početna

Pointer, adresa, vrijednost (objasnjenje gradiva)
WWW:

Moja sarma
 
Započnite novu temu   Odgovorite na temu   printer-friendly view    Forum@DeGiorgi: Početna -> Kolegiji 2. godine -> Strukture podataka i algoritmi
Prethodna tema :: Sljedeća tema  
Autor/ica Poruka
Marvin
Forumaš(ica)
Forumaš(ica)


Pridružen/a: 01. 12. 2006. (15:46:10)
Postovi: (56)16
Sarma = la pohva - posuda
52 = 56 - 4

PostPostano: 18:24 sub, 23. 10. 2010    Naslov: Pointer, adresa, vrijednost Citirajte i odgovorite

Imam dojam da ponekad nije jasno čemu služe "zvjezdice" i "ampersandi" i zašto se u definiciji funkcije pojavljuje zvjezdica, a u programskom kôdu ponekad javljaju zvjezdice ili ampersandi kraj varijable dok drugi put ne.

Zato ću napisati kratku priču kako ja to vidim. Možda nekome pomogne.

[b]Mali uvod[/b]

U programskom jeziku C svi identifikatori koji se koriste (kao što su varijable, funkcije) trebaju se prije korištenja deklarirati. Na primjer ako želite koristiti neki cijeli broj, tada pišete
[code:1]int broj;[/code:1]
Time ste rekli da ćete koristiti varijablu pod imenom "broj" i da ona treba spremati cijele brojeve. Kompajler koristi vaše deklaracije da bi provjerio da li ih poštujete, i upozorio vas ako ste ih prekršili. Time se želi smanjiti broj grešaka u programiranju (da slučajno pridružite realni broj varijabli koja čuva cijeli, izgubili bi preciznost koja vam možda treba - umjesto [tt]3.14[/tt], spremilo bi se moguće samo [tt]3[/tt]).

[b]Ukratko[/b]

Ugrubo i neprecizno prikažimo tipični primjer u kojem je se koristi *, & ili ništa, ovisno o prilici:

[code:1]
// u deklaraciji tražimo adresu od cijelog broja
void PrimjerFunkcije(int* i) /* deklaracija funkcije */
{
// pomoću operatora dereferenciranja imamo pristup vrijednosti upisanoj na adresi "i"
if (*i > 0)
{
*i = *i - 1;
// pozivamo PrimjerFunkcija tako što prosljeđujemo adresu "i"
PrimjerFunkcije(i);
}
}

int a = 13;
PrimjerFunkcije(&a); // za poziv funkcije trebamo slati adresu varijable a, pa koristimo adresni operator da bi dobili adresu "&a"
[/code:1]

Preciznije i detaljnije objašnjenje možete pročitati niže. Prvi naslov možete preskočiti ako ne volite analogije.

[b]Gradilište[/b]

Zamislite da ste vi šef projekta nekog gradilišta. Da bi ga izgradili zgradu, trebate napraviti dobar redoslijed izgradnje. Računalni program je kao plan izgradnje. Da bi se znalo točno tko sudjeluje u nekom dijelu posla (materijal ili izvođač), trebate sudionicima zadati jedinstvena imena. Ta imena su identifikatori. Kada prvi put uvodite sudionika, kažete i kakvi su sudionici - njihov tip (je li to stup duljine 80 cm i promjera 20 cm izrađen od betona ili je to radnik-keramičar).
Ako sve to napravite, neki vaš nadglednik može provjeriti je li vaš plan izgradnje dobar (ako ste za sve sudionike zapisali njihov tip i jeste li se pridržavali toga da svaki sudionik sudjeluje u točno zadanom tipu zadatka). Nadglednik-kompajler osim toga i provodi vaš plan (kompajlira kôd).

Deklaraciju možete gledati kao pravilo, ugovor. Vi ugovorite s kompajlerom da ćete u "[tt]broj[/tt]" spremati cijeli broj. On pak pri provođenju plana (kompajliranju programskog kôda) provjerava jeste li se vi sâmi držali plana.

Nekad je projekt preveliki bi se mogao potrpati u jedan plan. U tom slučaju zapošljavate nekog podizvođača radova. On ne treba znati cijeli plan izgradnje. Dovoljno mu je da zna što može očekivati od vas i što vi očekujete da on napravi. Zbog gospodarske krize, ljudi su nepovjerljivi, pa se i sa podizvođačem potpisuje ugovor. U tom ugovoru stoji točno što vi morate dati podizvođaču da on obavi posao i što točno očekujete od njega.

Funkciju možete gledati kao podizvođača radova. Ugovor koji potpisujete je deklaracija funkcije. Očekivani ulaz s vaše strane su parametri funkcije. Funkcija obavlja neku radnju i može vam vratiti neki povratni rezultat.

[i]Kako[/i] želite da funkcija-podizvođač izvrši radove, to možete napisati u posebnom manjem planu ili pustiti da tvrtka podizvođač to riješi sama. [i]Kako[/i] je tijelo funkcije i u njemu piše kako od ulaza dobiti izlaz.

[b]Malo o sintaksi jezika [tt]C[/tt][/b]

Možemo zamisliti da računala pohranjuju podatke na nekim mjestima koja su jedinstveno određena brojem. Taj broj koji ih određuje nazivamo adresa.

Jezik C nam omogućava da se približimo stvarnom zapisu podataka na računalu tako što možemo baratati adresama. Zbog toga za svaki tip ([tt]int[/tt], [tt]double[/tt],...) postoji i tip za njegovu adresu ([tt]int*[/tt] - tip za adrese tipa int, [tt]double*[/tt] - tip adresa tipa double). Osim toga pomažu nam i operatori [tt]&[/tt] i [tt]*[/tt].
[code:1]
int broj = 3;
int* adresa_broja = &broj;
int drugi_broj = *adresa_broja;
[/code:1]

Prvo deklariramo i inicijaliziramo jedan cijeli broj "[tt]broj[/tt]" na vrijednost 3.

Nakon toga deklariramo tip adrese cijelog broja [tt]int*[/tt] i inicijaliziramo ga sa adresom od cijelog broja "[tt]broj[/tt]". Adresni operator [tt]&[/tt] nam pri tom vraća adresu od varijable "[tt]broj[/tt]".

Na kraju deklariramo cijeli broj "[tt]drugi_broj[/tt]" i inicijaliziramo ga pomoću [i]vrijednosti zapisane na adresi[/i] "[tt]adresa_broja[/tt]". Kako bi dobili pristup vrijednosti zapisanoj na nekoj adresi koristimo operator dereferenciranja [tt]*[/tt].

Prva nejasnoća obično nastaje zbog zvjezdice koja je naziv operatora a istodobno opisuje i tip. Druga nejasnoća obično nastaje u tome što u kojem kontekstu znači vrijednost.

Navedimo neke primjere:
[code:1]
int* a; // Deklarirali smo varijablu tipa "adresa cjelobrojnog tipa" čiji je identifikator "a"
int *b; // Deklarirali smo varijablu tipa "adresa cjelobrojnog tipa" čiji je identifikator "b"

int c = 13;
a = &c; // U varijablu "a" zapisali smo adresu od cjelobrojnog tipa "c"

int d;
d = *a; // U varijablu "d" zapisali smo vrijednost na adresi koja je zapisana u varijabli "a"
[/code:1]

Nejasnoća nastaje jer sintaksa jezika C dopušta da se tip adrese nekog tipa piše bilo [tt]tip *[/tt] ili [tt]tip*[/tt].
U gornjem bloku koda imamo [tt]int *b[/tt] i [tt]d = *a[/tt]. U prvom slučaju zvjezdica se zajedno sa [tt]int[/tt] tumači kao naziv za tip adrese cjelobrojnog tipa. U drugom slučaju zvjezdica je operator kojom pristupamo vrijednosti zapisanoj na adresi zapisanoj u varijabli [tt]a[/tt]. Značenje zvjezdice ovisi o kontekstu.

[b]Što je vrijednost?[/b]

Nejasnoća s vrijednosti nastaje jer se ponekad naziv vrijednost koristi kao nekakva suprotnost adresi. Za primjer opet navodimo isječak kôda:
[code:1]
int a = 13;
int* pa = &a;
[/code:1]
Ponekad ćete čuti da se govori u [tt]pa[/tt] je zapisana adresa. To je malo neprecizno. U varijablama se [i]uvijek[/i] pišu neke vrijednosti. Te vrijednosti mogu biti različitog tipa: cjelobrojne, pomičnog zareza, adrese nekog cijelog broja, adrese nekog broja s pomičnim zarezom, itd.

Neka je cijeli broj 5 zapisan na adresi 137. To prikazujemo ovako: [tt]137 [5][/tt]. Na [i]adresi[/i] 137 je zapisana [i]vrijednost[/i] 5.

Zapišimo sad na neku drugu lokaciju određenu nekom drugom adresom "adresu" od [tt]a[/tt]. Na [i]drugoj adresi[/i] je zapisana [i]vrijednost[/i] adrese na kojoj je zapisan broj 5 -- [tt]478 [137][/tt].
[code:1]
int a = 5; // deklariramo i inicijaliziramo cijeli broj 5; pretpostavimo da je zapisan na adresi 137.
int* pa = &a; // sada je na nekoj novoj adresi zapisana vrijednost 137 - vrijednost adrese od a.
int** ppa = &pa; // a na trećoj adresi je zapisana vrijednost adrese na kojoj je sadržana vrijednost adrese od a.
[/code:1]
Drugim riječima, na adresama su uvijek zapisane neke vrijednosti. Te vrijednosti se ovisno o tipu varijable s kojom su vezane tumače kao cijeli brojevi ili adrese cijelih brojeva. To se u jeziku C može i lako vidjeti korištenjem funkcije [tt]printf[/tt] - printf će ispisati vrijednost zapisanu na nekoj adresi kao broj ili kao slovo, ovisno o tome pozovete li ga sa parametrom [tt]"%d"[/tt] ili [tt]"%c"[/tt].

[b]Vrijednost i funkcija[/b]

Nepreciznost oko adrese i vrijednosti se često može sresti i kod funkcija.
[code:1]
void nista(BTREE* PT)
{
// ne radi ništa
}
[/code:1]
Možda bih u ovakvoj situaciji rekao: "Funkciji šaljemo binarno stablo po adresi" ili "funkciji šaljemo adresu". Ono što je malo preciznije je da funkciji šaljemo [i]vrijednost adrese na kojoj je zapisano binarno stablo[/i].
Kad funkcija primi tu vrijednost, ona ju može iskoristiti kako bi došla do vrijednosti binarnog stabla. Operator dereferenciranja [tt]*[/tt] nam omogućava pristupanje vrijednostima zapisanim na nekoj adresi. [tt]*PT[/tt] će zato vratiti vrijednost binarnog stabla zapisanog u varijabli PT čiji je tip adresa binarnog stabla.

Prikažimo sada neku stvarnu funkciju:
[code:1]
void obidiStablo( node n, BTREE B, labeltype *max, int *nadjen )
{
if( n == LAMBDA ) return;

if( !jeList( n, B ) && bratOK( n, B ) && brojPotomaka( n, B ) >= 5 )
if( *nadjen == 0 || *max < LABEL( n, B ) )
{
*nadjen = 1;
*max = LABEL( n, B );
}

obidiStablo( LEFT_CHILD( n, B ), B, max, nadjen );
obidiStablo( RIGHT_CHILD( n, B ), B, max, nadjen );
}
[/code:1]

Prvi redak je deklaracija (ugovor). U njemu kažete da ćete vi dati funkciji čvor ([tt]node n[/tt]), binarno stablo ([tt]BTREE B[/tt]), adresu oznake ([tt]labeltype *maxi[/tt]) i adresu cijelog broja ([tt]int *nadjen[/tt]). Vi ćete ustvari dati [i]vrijednosti[/i] čvora, stabla, adrese oznake i adrese cijelog broja.

Kako bi funkcija promijenila vrijednost zapisanu na nekoj adresi, koristi operator dereferenciranja da bi pristupila vrijednosti zapisanoj na toj adresi.

Kada se obavljaju rekurzivni pozivi, primljena vrijednost adrese se jednostavno proslijedi u iduće pozive.

Još jednom:
[list]
[*]u deklaraciji funkcije mi zadajemo pravila (...,očekujemo vrijednost tipa adresa labeltypea koju identificiramo sa max, očekujemo vrijednost tipa adresa cijelog broja koju identificiramo sa imenom nadjen)
[*]u kôdu prosljeđujemo vrijednosti prema zadanim pravilima (...,šaljemo vrijednosti adrese na kojoj je zapisan labeltype, šaljemo vrijednost adrese na kojoj je zapisan cijeli broj)
[/list:u]
Vratimo se na funkciju sa početka:
[code:1]
// deklaracija funkcije; očekujemo ulazni podatak tipa "adresa cijelog broja"; njegovu vrijednost
void PrimjerFunkcije(int *i)
{
// ako je vrijednost upisana na adresi čija je vrijednost primljena kao ulazni podatak > 0
if (*i > 0)
{
// vrijednosti upisanoj na adresi određenoj primljenom vrijednosti adrese oduzmi 1
*i = *i - 1;
// pozovi PrimjerFunkcije -- samo proslijedimo vrijednost podatka tipa "adresa cijelog broja" koji smo primili
PrimjerFunkcije(i);
}
}

int a = 16;
PrimjerFunkcije(&a); // pozivamo funkciju -- trebamo joj poslati vrijednost adrese cijelog broja prema prototipu -- adresni operator nam daje vrijednost adrese na kojoj je zapisana vrijednost varijable a
[/code:1]

[b]Nazad na gradilište[/b]

U Stvarnom Svijetu, jedan čovjek teško može sam napisati kompleksniji softver. Zato se posao dijeli na razne načine.

Na primjer, jedna tvrtka može napisati skup funkcija, koji se naziva biblioteka. Korisnik bibliotete zna samo što mora poslati u neku funkciju, te što može očekivati kao rezultat. On nema pristup implementaciji funkcije (tijelu). Tijelo se može i mijenjati s vremenom (radi povećanja brzine, sigurnosti, kompatibilnosti,...). Takve biblioteke ste sigurno već i koristili (C++ STL ili neki header file u običnom C-u).
Drugi primjer su web servisi - definirano je što se šalje na neku web adresu i što se vraća kao rezultat (vremenska prognoza za traženo razdoblje).

Zato analogija gradilišta i nije toliko nepovezana koliko se čini na prvi pogled.

[b]Ograda[/b]

Moguće je da sam i u "detaljnijem" objašnjenu nešto namjerno ili nenamjerno propustio, pogriješio ili neprecizno napisao.
Svakako pitajte ako vam nešto nije jasno [b]prije[/b] kolokvija - možete mi slati i mail.

[b]Osobno mišljenje[/b]
Na nižim godinama često postoji navika nepostavljanja pitanja.

Kod nas je to bilo približno ovako: na prvoj godini je netko još i postavio pitanje - ako je pitanje bilo prejednostavno po sudu većine, onda je osoba doživjela okretanje očima ili podsmijeh.
Ako pak je bilo prekomplicirano, onda je doživjela okretanje očima i iščuđavanje. Nakon nekog vremena, više se ništa nije pitalo (ili se pitalo kolegu do vas, da izbjegnete osjećaj srama).

Shvaćam da postoje razlike u predznanju i uloženom trudu. Isto tako shvaćam i sukob interesa: oni koji imaju bolje predznanje ili ulažu više truda ne žele trošiti vrijeme na stvari koje su im jasne. S druge strane, oni kojima imaju poteškoća s razumijevanjem žele da im se gradivo približi na satu - iz knjige mogu učiti i kod kuće.

Ja mislim da se ne bi smjele događati situacije u kojima je studentu neugodno postavljati pitanja. Skoro jedina prednost nastave je da možete uživo pitati za pojašnjenja (inače možete gledati i screencast sa sveučilišta Yale, Berkeley, MIT,...). Ako su već "očita", a treba obraditi gradivo, mogu to odraditi pod pauzom, pokušati vas uputiti na neki materijal ili pojasniti pitanje preko maila. Ako ne uspijem, nemojte kriviti sebe, nego mene i pokušajte sa dodatnim pitanjima (naravno to ne znači da ne trebate ništa proučiti sami).

Ilija Pavlic.
Imam dojam da ponekad nije jasno čemu služe "zvjezdice" i "ampersandi" i zašto se u definiciji funkcije pojavljuje zvjezdica, a u programskom kôdu ponekad javljaju zvjezdice ili ampersandi kraj varijable dok drugi put ne.

Zato ću napisati kratku priču kako ja to vidim. Možda nekome pomogne.

Mali uvod

U programskom jeziku C svi identifikatori koji se koriste (kao što su varijable, funkcije) trebaju se prije korištenja deklarirati. Na primjer ako želite koristiti neki cijeli broj, tada pišete
Kod:
int broj;

Time ste rekli da ćete koristiti varijablu pod imenom "broj" i da ona treba spremati cijele brojeve. Kompajler koristi vaše deklaracije da bi provjerio da li ih poštujete, i upozorio vas ako ste ih prekršili. Time se želi smanjiti broj grešaka u programiranju (da slučajno pridružite realni broj varijabli koja čuva cijeli, izgubili bi preciznost koja vam možda treba - umjesto 3.14, spremilo bi se moguće samo 3).

Ukratko

Ugrubo i neprecizno prikažimo tipični primjer u kojem je se koristi *, & ili ništa, ovisno o prilici:

Kod:

// u deklaraciji tražimo adresu od cijelog broja
void PrimjerFunkcije(int* i) /* deklaracija funkcije */
{
   // pomoću operatora dereferenciranja imamo pristup vrijednosti upisanoj na adresi "i"
   if (*i > 0)
   {
      *i = *i - 1;
      // pozivamo PrimjerFunkcija tako što prosljeđujemo adresu "i"
      PrimjerFunkcije(i);
   }
}

int a = 13;
PrimjerFunkcije(&a); // za poziv funkcije trebamo slati adresu varijable a, pa koristimo adresni operator da bi dobili adresu "&a"


Preciznije i detaljnije objašnjenje možete pročitati niže. Prvi naslov možete preskočiti ako ne volite analogije.

Gradilište

Zamislite da ste vi šef projekta nekog gradilišta. Da bi ga izgradili zgradu, trebate napraviti dobar redoslijed izgradnje. Računalni program je kao plan izgradnje. Da bi se znalo točno tko sudjeluje u nekom dijelu posla (materijal ili izvođač), trebate sudionicima zadati jedinstvena imena. Ta imena su identifikatori. Kada prvi put uvodite sudionika, kažete i kakvi su sudionici - njihov tip (je li to stup duljine 80 cm i promjera 20 cm izrađen od betona ili je to radnik-keramičar).
Ako sve to napravite, neki vaš nadglednik može provjeriti je li vaš plan izgradnje dobar (ako ste za sve sudionike zapisali njihov tip i jeste li se pridržavali toga da svaki sudionik sudjeluje u točno zadanom tipu zadatka). Nadglednik-kompajler osim toga i provodi vaš plan (kompajlira kôd).

Deklaraciju možete gledati kao pravilo, ugovor. Vi ugovorite s kompajlerom da ćete u "broj" spremati cijeli broj. On pak pri provođenju plana (kompajliranju programskog kôda) provjerava jeste li se vi sâmi držali plana.

Nekad je projekt preveliki bi se mogao potrpati u jedan plan. U tom slučaju zapošljavate nekog podizvođača radova. On ne treba znati cijeli plan izgradnje. Dovoljno mu je da zna što može očekivati od vas i što vi očekujete da on napravi. Zbog gospodarske krize, ljudi su nepovjerljivi, pa se i sa podizvođačem potpisuje ugovor. U tom ugovoru stoji točno što vi morate dati podizvođaču da on obavi posao i što točno očekujete od njega.

Funkciju možete gledati kao podizvođača radova. Ugovor koji potpisujete je deklaracija funkcije. Očekivani ulaz s vaše strane su parametri funkcije. Funkcija obavlja neku radnju i može vam vratiti neki povratni rezultat.

Kako želite da funkcija-podizvođač izvrši radove, to možete napisati u posebnom manjem planu ili pustiti da tvrtka podizvođač to riješi sama. Kako je tijelo funkcije i u njemu piše kako od ulaza dobiti izlaz.

Malo o sintaksi jezika C

Možemo zamisliti da računala pohranjuju podatke na nekim mjestima koja su jedinstveno određena brojem. Taj broj koji ih određuje nazivamo adresa.

Jezik C nam omogućava da se približimo stvarnom zapisu podataka na računalu tako što možemo baratati adresama. Zbog toga za svaki tip (int, double,...) postoji i tip za njegovu adresu (int* - tip za adrese tipa int, double* - tip adresa tipa double). Osim toga pomažu nam i operatori & i *.
Kod:

int broj = 3;
int* adresa_broja = &broj;
int drugi_broj = *adresa_broja;


Prvo deklariramo i inicijaliziramo jedan cijeli broj "broj" na vrijednost 3.

Nakon toga deklariramo tip adrese cijelog broja int* i inicijaliziramo ga sa adresom od cijelog broja "broj". Adresni operator & nam pri tom vraća adresu od varijable "broj".

Na kraju deklariramo cijeli broj "drugi_broj" i inicijaliziramo ga pomoću vrijednosti zapisane na adresi "adresa_broja". Kako bi dobili pristup vrijednosti zapisanoj na nekoj adresi koristimo operator dereferenciranja *.

Prva nejasnoća obično nastaje zbog zvjezdice koja je naziv operatora a istodobno opisuje i tip. Druga nejasnoća obično nastaje u tome što u kojem kontekstu znači vrijednost.

Navedimo neke primjere:
Kod:

int* a; // Deklarirali smo varijablu tipa "adresa cjelobrojnog tipa" čiji je identifikator "a"
int *b; // Deklarirali smo varijablu tipa "adresa cjelobrojnog tipa" čiji je identifikator "b"

int c = 13;
a = &c; // U varijablu "a" zapisali smo adresu od cjelobrojnog tipa "c"

int d;
d = *a; // U varijablu "d" zapisali smo vrijednost na adresi koja je zapisana u varijabli "a"


Nejasnoća nastaje jer sintaksa jezika C dopušta da se tip adrese nekog tipa piše bilo tip * ili tip*.
U gornjem bloku koda imamo int *b i d = *a. U prvom slučaju zvjezdica se zajedno sa int tumači kao naziv za tip adrese cjelobrojnog tipa. U drugom slučaju zvjezdica je operator kojom pristupamo vrijednosti zapisanoj na adresi zapisanoj u varijabli a. Značenje zvjezdice ovisi o kontekstu.

Što je vrijednost?

Nejasnoća s vrijednosti nastaje jer se ponekad naziv vrijednost koristi kao nekakva suprotnost adresi. Za primjer opet navodimo isječak kôda:
Kod:

int a = 13;
int* pa = &a;

Ponekad ćete čuti da se govori u pa je zapisana adresa. To je malo neprecizno. U varijablama se uvijek pišu neke vrijednosti. Te vrijednosti mogu biti različitog tipa: cjelobrojne, pomičnog zareza, adrese nekog cijelog broja, adrese nekog broja s pomičnim zarezom, itd.

Neka je cijeli broj 5 zapisan na adresi 137. To prikazujemo ovako: 137 [5]. Na adresi 137 je zapisana vrijednost 5.

Zapišimo sad na neku drugu lokaciju određenu nekom drugom adresom "adresu" od a. Na drugoj adresi je zapisana vrijednost adrese na kojoj je zapisan broj 5 – 478 [137].
Kod:

int a = 5; // deklariramo i inicijaliziramo cijeli broj 5; pretpostavimo da je zapisan na adresi 137.
int* pa = &a; // sada je na nekoj novoj adresi zapisana vrijednost 137 - vrijednost adrese od a.
int** ppa = &pa; // a na trećoj adresi je zapisana vrijednost adrese na kojoj je sadržana vrijednost adrese od a.

Drugim riječima, na adresama su uvijek zapisane neke vrijednosti. Te vrijednosti se ovisno o tipu varijable s kojom su vezane tumače kao cijeli brojevi ili adrese cijelih brojeva. To se u jeziku C može i lako vidjeti korištenjem funkcije printf - printf će ispisati vrijednost zapisanu na nekoj adresi kao broj ili kao slovo, ovisno o tome pozovete li ga sa parametrom "%d" ili "%c".

Vrijednost i funkcija

Nepreciznost oko adrese i vrijednosti se često može sresti i kod funkcija.
Kod:

void nista(BTREE* PT)
{
   // ne radi ništa
}

Možda bih u ovakvoj situaciji rekao: "Funkciji šaljemo binarno stablo po adresi" ili "funkciji šaljemo adresu". Ono što je malo preciznije je da funkciji šaljemo vrijednost adrese na kojoj je zapisano binarno stablo.
Kad funkcija primi tu vrijednost, ona ju može iskoristiti kako bi došla do vrijednosti binarnog stabla. Operator dereferenciranja * nam omogućava pristupanje vrijednostima zapisanim na nekoj adresi. *PT će zato vratiti vrijednost binarnog stabla zapisanog u varijabli PT čiji je tip adresa binarnog stabla.

Prikažimo sada neku stvarnu funkciju:
Kod:

void obidiStablo( node n, BTREE B, labeltype *max, int *nadjen )
{
    if( n == LAMBDA ) return;
   
    if( !jeList( n, B ) && bratOK( n, B ) && brojPotomaka( n, B ) >= 5 )
        if( *nadjen == 0 || *max < LABEL( n, B ) )
        {
            *nadjen = 1;
            *max = LABEL( n, B );
        }

    obidiStablo( LEFT_CHILD( n, B ), B, max, nadjen );
    obidiStablo( RIGHT_CHILD( n, B ), B, max, nadjen );
}


Prvi redak je deklaracija (ugovor). U njemu kažete da ćete vi dati funkciji čvor (node n), binarno stablo (BTREE B), adresu oznake (labeltype *maxi) i adresu cijelog broja (int *nadjen). Vi ćete ustvari dati vrijednosti čvora, stabla, adrese oznake i adrese cijelog broja.

Kako bi funkcija promijenila vrijednost zapisanu na nekoj adresi, koristi operator dereferenciranja da bi pristupila vrijednosti zapisanoj na toj adresi.

Kada se obavljaju rekurzivni pozivi, primljena vrijednost adrese se jednostavno proslijedi u iduće pozive.

Još jednom:

  • u deklaraciji funkcije mi zadajemo pravila (...,očekujemo vrijednost tipa adresa labeltypea koju identificiramo sa max, očekujemo vrijednost tipa adresa cijelog broja koju identificiramo sa imenom nadjen)
  • u kôdu prosljeđujemo vrijednosti prema zadanim pravilima (...,šaljemo vrijednosti adrese na kojoj je zapisan labeltype, šaljemo vrijednost adrese na kojoj je zapisan cijeli broj)

Vratimo se na funkciju sa početka:
Kod:

// deklaracija funkcije; očekujemo ulazni podatak tipa "adresa cijelog broja"; njegovu vrijednost
void PrimjerFunkcije(int *i)
{
   // ako je vrijednost upisana na adresi čija je vrijednost primljena kao ulazni podatak > 0
   if (*i > 0)
   {
      // vrijednosti upisanoj na adresi određenoj primljenom vrijednosti adrese oduzmi 1
      *i = *i - 1;
      // pozovi PrimjerFunkcije -- samo proslijedimo vrijednost podatka tipa "adresa cijelog broja" koji smo primili
      PrimjerFunkcije(i);
   }
}

int a = 16;
PrimjerFunkcije(&a); // pozivamo funkciju -- trebamo joj poslati vrijednost adrese cijelog broja prema prototipu -- adresni operator nam daje vrijednost adrese na kojoj je zapisana vrijednost varijable a


Nazad na gradilište

U Stvarnom Svijetu, jedan čovjek teško može sam napisati kompleksniji softver. Zato se posao dijeli na razne načine.

Na primjer, jedna tvrtka može napisati skup funkcija, koji se naziva biblioteka. Korisnik bibliotete zna samo što mora poslati u neku funkciju, te što može očekivati kao rezultat. On nema pristup implementaciji funkcije (tijelu). Tijelo se može i mijenjati s vremenom (radi povećanja brzine, sigurnosti, kompatibilnosti,...). Takve biblioteke ste sigurno već i koristili (C++ STL ili neki header file u običnom C-u).
Drugi primjer su web servisi - definirano je što se šalje na neku web adresu i što se vraća kao rezultat (vremenska prognoza za traženo razdoblje).

Zato analogija gradilišta i nije toliko nepovezana koliko se čini na prvi pogled.

Ograda

Moguće je da sam i u "detaljnijem" objašnjenu nešto namjerno ili nenamjerno propustio, pogriješio ili neprecizno napisao.
Svakako pitajte ako vam nešto nije jasno prije kolokvija - možete mi slati i mail.

Osobno mišljenje
Na nižim godinama često postoji navika nepostavljanja pitanja.

Kod nas je to bilo približno ovako: na prvoj godini je netko još i postavio pitanje - ako je pitanje bilo prejednostavno po sudu većine, onda je osoba doživjela okretanje očima ili podsmijeh.
Ako pak je bilo prekomplicirano, onda je doživjela okretanje očima i iščuđavanje. Nakon nekog vremena, više se ništa nije pitalo (ili se pitalo kolegu do vas, da izbjegnete osjećaj srama).

Shvaćam da postoje razlike u predznanju i uloženom trudu. Isto tako shvaćam i sukob interesa: oni koji imaju bolje predznanje ili ulažu više truda ne žele trošiti vrijeme na stvari koje su im jasne. S druge strane, oni kojima imaju poteškoća s razumijevanjem žele da im se gradivo približi na satu - iz knjige mogu učiti i kod kuće.

Ja mislim da se ne bi smjele događati situacije u kojima je studentu neugodno postavljati pitanja. Skoro jedina prednost nastave je da možete uživo pitati za pojašnjenja (inače možete gledati i screencast sa sveučilišta Yale, Berkeley, MIT,...). Ako su već "očita", a treba obraditi gradivo, mogu to odraditi pod pauzom, pokušati vas uputiti na neki materijal ili pojasniti pitanje preko maila. Ako ne uspijem, nemojte kriviti sebe, nego mene i pokušajte sa dodatnim pitanjima (naravno to ne znači da ne trebate ništa proučiti sami).

Ilija Pavlic.




Zadnja promjena: Marvin; 20:14 sub, 23. 10. 2010; ukupno mijenjano 1 put.
[Vrh]
Korisnički profil Pošaljite privatnu poruku
manbearpig
Forumaš(ica)
Forumaš(ica)


Pridružen/a: 31. 01. 2009. (19:53:28)
Postovi: (40)16
Spol: žensko
Sarma = la pohva - posuda
-6 = 10 - 16
Lokacija: socijalno nelagodne situacije TAMO SAM

PostPostano: 19:06 sub, 23. 10. 2010    Naslov: Citirajte i odgovorite

najbolji asistent ikad.
najbolji asistent ikad.



_________________
from the top of the ocean yeah
to the bottom of the sky goddamn
well i get claustrophobic
i can you know that i can
[Vrh]
Korisnički profil Pošaljite privatnu poruku Posjetite Web stranice
Prethodni postovi:   
Započnite novu temu   Odgovorite na temu   printer-friendly view    Forum@DeGiorgi: Početna -> Kolegiji 2. godine -> Strukture podataka i algoritmi Vremenska zona: GMT + 01:00.
Stranica 1 / 1.

 
Forum(o)Bir:  
Ne možete otvarati nove teme.
Ne možete odgovarati na postove.
Ne možete uređivati Vaše postove.
Ne možete izbrisati Vaše postove.
Ne možete glasovati u anketama.
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2002 phpBB Group
Theme created by Vjacheslav Trushkin
HR (Cro) by Ančica Sečan