PDA

Prikaži potpunu verziju : Pointeri, da li je ovo dobar primer?


milosh-96
27.9.2017, 15:34
Počeo sam da učim C jezik (već dosta dobro znam PHP i Python, i donekle Javu) i najviše me zbunjuju pointeri u C-u. Razumem da oni umestio vrednosti (value) skladište adresu u memoriji varijable na koju pokazuju. Nije mi jasno kada se primenjuju u praksi.

Zato sam napisao ovaj mali program u kojem koristim pointere.

Zanima me da li ovaj primer ima smisla, bar kada su pointeri u pitanju.

Šta program radi: Na početku timovi imaju početne bodove, nakon toga korisnik mora da izabere jedan od timova, zatim se broj poena za izabrani tim povećava za jedan i korisnik dobija rezultat.



#include <stdio.h>

int main() {
int *team_pts,defnum,input;
defnum = 0;
team_pts = &defnum;
struct stats {
int pts,wins,losses,draws,gs,gc,gd;
};
struct stats inter;
inter.pts = 5;
struct stats milan;
milan.pts = 3;

printf("Select your Team:\n1.Inter\n2.Milan\n");
scanf("%d",&input);
printf("*****************\n\n");
switch(input) {
case 1:
team_pts = &inter.pts;
break;
case 2:
team_pts = &milan.pts;
break;
}

*team_pts += 1;

printf("TEAM POINTS: %d",*team_pts);

getchar();
return 0;

}

Neutrino
27.9.2017, 15:58
Pokazivači se koriste u slučajevima kada algoritam ili upotrebljene strukture podataka imaju koristi od direktne manipulacije memorijom. Recimo, strukture podataka kao što su ulančane liste (linked lists) i stabla (trees) za svaki element pored korisnog podatka sadrže i informacije o lokaciji elemenata u memoriji koji su na neki način funkcionalno povezani sa datim elementom (sledeći/prethodni element jednostruko/dvostruko ulančane liste, čvorovi binarnog stabla itd.).

Dakle, u situacijama kada algoritam može bez problema da koristi primitivne tipove podataka kao što su celi brojevi (int) itd. nema nikakvog smisla da se situacija komplikuje korišćenjem pokazivača na njih jer se pod haubom taj proces automatski odvija tokom prevođenja (kompajliranja) i izvršavanja.

Isto tako, pokazivači su nezamenjljiv alat kod algoritama koji koriste dinamičku alokaciju memorije (dynamic memory allocation).

voodoo_
27.9.2017, 21:22
Drugi primer, funkcije koje operišu nad strukturama ili objektima neke klase, to jest primaju strukturu ili objekat kao argument.

Seti se da argumenti funkcije zapravo predstavljaju lokalne kopije prosleđenih vrednosti, npr:

void f(int a)
{
a = 10; // 'a' je lokalna kopija prosleđenog 'int' argumenta, izmene se ne vide "napolju"
}

int main()
{
a = 5;
f(a);
printf("%d", a); // 'a' je ostalo 5

return 0;
}

E sad, zamisli da funkcija 'f' umesto int-a prima celu strukturu ili objekat. Em što bi morala da se napravi kompletna kopija prosleđene strukture, em se ništa što bi radio sa članovima te strukture ne bi odrazilo na originalnu strukturu prosleđenu toj funkciji.

Ali zato funkcija može da primi pointer na strukturu ili objekat, i preko pointera da dohvati originalni objekat i direktno ga modifikuje. Plus nema nikakvog dodatnog kopiranja u memoriji.

struct Osoba {
char Ime[20];
char Prezime[20];
};

void Funkcija1(struct Osoba o)
{
strcpy(o.Ime, "Pera");
}

void Funkcija2(struct Osoba *o)
{
strcpy(o->Ime, "Pera");
}

int main()
{
struct Osoba A = { "Mile", "Kitić" };

Funkcija1(A); // Promeniće 'Ime' u lokalnoj kopiji unutar funkcije, nema efekta na strukturu A
printf("%s", A.Ime); // Ispisaće "Mile"

Funkcija2(&A); // Preko adrese će prići stvarnom objektu A i promeniti mu polje 'Ime'
printf("%s", A.Ime); // Ispisaće "Pera"

return 0;
}

(U nekim drugim jezicima je ovo poznato kao "prosleđivanje argumenata po referenci" a ispod haube se implementira preko adresa objekta, odnosno pokazivača na objekat)

Djordje Turjacanin
28.9.2017, 0:27
Zamisli da imas neku ogromnu strukturu, npr. Niz od nekoliko hiljada intova, nekoliko hiljada double-ova i npr jedan int koji govori koliko ima elemenata koji nisu nula u tim nizovima. I sad imas jedan veliki niz elemenata takve strukture i hoces da ga sortiras po tome intu taj niz.

Kada ne bi koristio pokazivace, prilikom svake zamjene tri puta se kopira citava struktura koja je ogromna(jednom u privremeni element, jednom iz drugog u prvi i jednom iz privremenog u drugi) e sad zamisli koliko je to zahtjevno.

Medjutim, ako bi imao niz pokazivaca na elemente te strukture, prilikom zamjene ti ne kopiras citavu strukturu nego samo vrijednosti tri pokazivaca (tj. U sustini tri inta jer je pokazivac zapravo int). Eto to bi bio neki primjer upotrebe pokazivaca.

Teva
1.10.2017, 10:55
Primer je lep, al nema smisla što se tiče pokazivača :)

Nema smisla jer ti koristiš pokazivač za vrednost kojoj direktno imaš pristup u kontekstu gde je menjaš, pa nema nekog preteranog smisla koristiti pokazivač za nešto što već imaš.

Da bi ih bolje razumeo i kad imaju smisla i kad nemaju, moraš malo da proučiš kako računar izvršava tvoj kod i kako se organizuje memorija. Sta je stack, sta heap (sto se tice memorije ne struktura podataka), stek okvire i sve ono što prati celu tu priču.

I to je zapravo ono što je veoma bitno, jer pokazivači umeju da budu bolni izuzetno, pogotovo ako ih ne razumeš kako treba, a da bi razumeo pokazivače i zašto se koriste i gde, moraš da razumeš kako radi računar.

Meni su oni počeli da imaju smisla tek kad sam lepo to izučio, pre toga su mi bili mehanizam da pristupim onome što mi "ne pripada" :D