[ Boyka @ 28.10.2012. 17:42 ] @
Poceo sam se zanimati za C++ posle C#.net-a, i sada ne mogu da razumem gde se primenjuju pokazivaci i kako ja da znam gde da ga koristim?

Okej razumem da pokazivac obezbedjuje varijabli adresu u memomoriji, ali kako ja da znam kada da to koristim, kada recimo neke varijable u C++ nemaju adresno upisivanje, kako se one generisu u memoriji???

Nemojte mi slati suvisne linkove, procitao sam ih tone... Znaci vase najjednostavnije pojasnjenje kada da koristim pointer?
[ 4co_R @ 28.10.2012. 19:15 ] @
Pokazivač je mem lokacija koja sadrži adresu neke druge mem lokacije (tj. pokazuje na neku lokaciju).
Nije bas tako jednostavno reći gde treba a gde ne treba koristiti pokazivače, zavisi od trenutne situacije, ako ti nisu potrebni nemoj ih koristiti.
Kako budeš napredovao u c++ shvatićeš i njihovu upotrebu.

PS. Sigurno nisi stigao do dinamičke alokacije memorije.
[ Boyka @ 28.10.2012. 19:40 ] @
Znam to care, znaci ipak sa iskustvom dolazi i osecaj za pointere?

Tek sam juce poceo sa C++, a C sam ponekad ranije ucio, cisto iz neke radoznalosti, a C# znam duze vreme 2.5 godine
navikao sam na onu manu/vrlinu C#-a da sve sam odradi, ali sada me vuce srce blize 'metalu', pa sam se sada bacio na upoznavanje najsitnijih detalja pc-a, od najmanjeg tranzistora, preko kernela, kompajlera, pa sve do asm, c, c++-a...
[ deerbeer @ 28.10.2012. 20:02 ] @
Citat:

Znaci vase najjednostavnije pojasnjenje kada da koristim pointer?

Evo nekih situacija :

1.) Kada hoces da dinamicki alociras memoriju na heap-u
2.) Kad hoces da prosledjujes originalnu promenljivu/objekat nekoj funkciji ili drugom objektu itd umesto kreiranja kopije
3.) Kada hoces da koristis polimorfizam

Btw, u c# se svi slozeni tipovi prosledjuju pointerima samo je sintaksa drugacija tj. prostija ,
tako da ces lako moci da pronadjes primenu i u c++ -u ..
[ boyan3001 @ 28.10.2012. 22:22 ] @
Ono sto C# radi sa referentnim tipom podataka, to ti radis u C++ sa pokazivacima. Tako otprilike, ne bukvalno. C# ustvari maskira upotrebu pokazivaca, kao sto si rekao, mnogo toga sam odradjuje automatski. C++ ti dozvoljava da manipulises preciznije kad, sta i kako hoces da uradis sa objektima ili konkretnim podacima.
[ Boyka @ 28.10.2012. 22:23 ] @
Citat:
deerbeer: Evo nekih situacija :

1.) Kada hoces da dinamicki alociras memoriju na heap-u
2.) Kad hoces da prosledjujes originalnu promenljivu/objekat nekoj funkciji ili drugom objektu itd umesto kreiranja kopije
3.) Kada hoces da koristis polimorfizam

Btw, u c# se svi slozeni tipovi prosledjuju pointerima samo je sintaksa drugacija tj. prostija ,
tako da ces lako moci da pronadjes primenu i u c++ -u ..


Da, ali sam u C# zaista veoma retko koristio pokazivače...
Hvala vam na odgovorima, nadam se da mi neće mnogo vremena trebati da pređem sa C# na C++, na Javi sam posle mesec dana znao pola onoga što sam naučio u C#-u, C# mi dođe kao dorađena Java, dok C++ već na prvi pogled deluje dosta drugačiji, je l imao neko iskustva sa prelaskom sa C#-a na C++?
[ del-boy @ 29.10.2012. 00:06 ] @
Ako si radio iole nešto ozbiljnije u C#-u, koristio si pokazivače, samo što ih je, kao što je neko već rekao, C# uspešno skrivao od tebe.

Svaki put kad si radio nešto tipa Tip t = new Tip(), koristio si pokazivač, ili referencu, kako je C# naziva, ukoliko je Tip neka klasa.
Ono što se ovde desi je da C# na heap-u napravi objekat, a na stack stavi referencu na taj objekat. Uprošćeno, referenca ti je adresa tog kreiranog objekta na heap-u i na taj način možeš da mu pristupiš. Ukoliko je Tip value type (na primer struktura) onda se ne kreira objekat na heap-u nego na stacku i nemaš referencu. Identično se ponašaš i prema reference i prema value tipovima i kao klijenta te u većini slučajeva ni ne zanima šta je ispod. Razlika dolazi do izražaja kad prosleđuješ objekat kao parametar - ako je na heap-u prosledi se samo referenca, a ako je na stacku, pravi se kopija.

Kod c++-a je malo drugačije. Ti napraviš klasu, međutim u trenutku kreiranja instance biraš da li ćeš da li će objekat da se smesti na stack ili na heap. Tako recimo kod Tip t; kreira instancu klase Tip na stacku, dok Tip *t = new Tip(); kreira instancu na heap-u i pokazivač na tu instancu smešta u promenljivu t.

Ono što je bitna razlika je da u C#-u nemaš mogućnost menjanja vrednosti reference, dok u c++-u možeš da vršiš aritmetičke operacije nad pokazivačima. Moj omiljeni primer je pristupanje elementima niza. Kad napraviš niz, njegovo ime je samo referenca na lokaciju u memoriji, a indeksiranje je računanje adrese elementa sa zadatim indeksom. Pošto je ime niza samo adresa prvog elemnta, do njega možeš da dođeš tako što ćeš da dereferenciraš ime niza, na primer *niz. Ako hoćeš drugi element, dodaš jedan na početnu adresu i dobiješ *(niz + 1). Dalje, niz[index] može da se prevede u *(niz + index), što može da se se napiše kao *(index + niz), a to je jednako index[niz] ( niz[index] == index[niz] ).

Aritmetika pokazivača može biti mnogo moćna stvar kad ti treba. Moja preporuka je da kreneš da radiš, kucaj neke primere, prepiši par programa iz C#-a u C++ i biće ti dosta jasnije vremenom.

Ja pokazivače nisam skontao kako treba dok se nisam uhvatio u koštac sa asemblerom (do duše tad sam radio C, ali princip je isti), ali sa tim površnim poznavanjem sam uspevao razne stvari da odradim, na primer implementacija ulančane liste, što bi ti recimo bila odlična vežba za skontavanje pokazivača u C++-u ;)
[ boyan3001 @ 29.10.2012. 02:06 ] @
^
Odlicno objasnjenje. ;)
I ispravite me ako gresim, al' u C# referentni podatak - pokazivac moze da se koristi samo za rad sa dinamickim podacima, dok u C++ pokazivac moze da se koristi za bilo koji tip podataka.
[ Cortex85 @ 29.10.2012. 07:49 ] @
U c# postoje ref i out.

out
ref
[ deerbeer @ 29.10.2012. 08:20 ] @
Citat:

Da, ali sam u C# zaista veoma retko koristio pokazivače...

Nisi me shvatio . U sustini ih koristis non stop
C# nema pointere vec samo referentne tipove sto ce reci da se oni ponasaju kao pokazivaci , sa razlikama kao sto je ova :
Citat:

Ono što je bitna razlika je da u C#-u nemaš mogućnost menjanja vrednosti reference, dok u c++-u možeš da vršiš aritmetičke operacije nad pokazivačima.

i plus jos neke sintaksne razlike kao pozivanje metoda sa -> operatorom kao i njegovo dereferenciranje tj. dobijanje vrednosti objekta preko adrese sa * operatorom .


Citat:
boyan3001: ^
Odlicno objasnjenje.
I ispravite me ako gresim, al' u C# referentni podatak - pokazivac moze da se koristi samo za rad sa dinamickim podacima, dok u C++ pokazivac moze da se koristi za bilo koji tip podataka.

Tacno. I za to se koristi adresni operator & za inicijalizovanje pointera na bilo koji tip .

Code:

int i = 9  ; 
int* px = &i ; 

[ mmix @ 29.10.2012. 08:32 ] @
Citat:
boyan3001
I ispravite me ako gresim, al' u C# referentni podatak - pokazivac moze da se koristi samo za rad sa dinamickim podacima, dok u C++ pokazivac moze da se koristi za bilo koji tip podataka.


Mozes i u c#, samo je mehanika drugacija. Koristi se mehanizam boxinga u kome se value tip pretvara u objekat (svaki value tip u cli ima svoj klasni pandan), sto je u principu ekvivalentno oreferenci na kopiju value tipa. S tim sto i dalje ne mozes slobodno koristiti pointer aritmetiku. U osnovi u vecini slucajeva i nije neophodno, ako iterativno ideš kroz elemente niza for petljom JIT ce to kompajlirati preko pointer aritmetike.

Inace, nije bas tacno da c# nema pointer aritmetiku, samo je isključena u safe modu da bi background GC mogao nesmetano da pomera blokove u memoriji. Ako ukljucis unsafe mode i pinujes blok u heapu (efektivno pretvarajuci c# referencu u c++-like pointer) mozes korisiti PA. Vise detalja ovde: http://msdn.microsoft.com/en-us/library/t2yzs44b.aspx



[ Boyka @ 29.10.2012. 08:51 ] @
Citat:
del-boy:
Ako si radio iole nešto ozbiljnije u C#-u, koristio si pokazivače, samo što ih je, kao što je neko već rekao, C# uspešno skrivao od tebe.

Svaki put kad si radio nešto tipa Tip t = new Tip(), koristio si pokazivač, ili referencu, kako je C# naziva, ukoliko je Tip neka klasa.
Ono što se ovde desi je da C# na heap-u napravi objekat, a na stack stavi referencu na taj objekat. Uprošćeno, referenca ti je adresa tog kreiranog objekta na heap-u i na taj način možeš da mu pristupiš. Ukoliko je Tip value type (na primer struktura) onda se ne kreira objekat na heap-u nego na stacku i nemaš referencu. Identično se ponašaš i prema reference i prema value tipovima i kao klijenta te u većini slučajeva ni ne zanima šta je ispod. Razlika dolazi do izražaja kad prosleđuješ objekat kao parametar - ako je na heap-u prosledi se samo referenca, a ako je na stacku, pravi se kopija.

Kod c++-a je malo drugačije. Ti napraviš klasu, međutim u trenutku kreiranja instance biraš da li ćeš da li će objekat da se smesti na stack ili na heap. Tako recimo kod Tip t; kreira instancu klase Tip na stacku, dok Tip *t = new Tip(); kreira instancu na heap-u i pokazivač na tu instancu smešta u promenljivu t.

Ono što je bitna razlika je da u C#-u nemaš mogućnost menjanja vrednosti reference, dok u c++-u možeš da vršiš aritmetičke operacije nad pokazivačima. Moj omiljeni primer je pristupanje elementima niza. Kad napraviš niz, njegovo ime je samo referenca na lokaciju u memoriji, a indeksiranje je računanje adrese elementa sa zadatim indeksom. Pošto je ime niza samo adresa prvog elemnta, do njega možeš da dođeš tako što ćeš da dereferenciraš ime niza, na primer *niz. Ako hoćeš drugi element, dodaš jedan na početnu adresu i dobiješ *(niz + 1). Dalje, niz[index] može da se prevede u *(niz + index), što može da se se napiše kao *(index + niz), a to je jednako index[niz] ( niz[index] == index[niz] ).

Aritmetika pokazivača može biti mnogo moćna stvar kad ti treba. Moja preporuka je da kreneš da radiš, kucaj neke primere, prepiši par programa iz C#-a u C++ i biće ti dosta jasnije vremenom.

Ja pokazivače nisam skontao kako treba dok se nisam uhvatio u koštac sa asemblerom (do duše tad sam radio C, ali princip je isti), ali sa tim površnim poznavanjem sam uspevao razne stvari da odradim, na primer implementacija ulančane liste, što bi ti recimo bila odlična vežba za skontavanje pokazivača u C++-u ;)


Aha, a recimo klasa SqlConnection con = new SqlConnection(); da li je i ona u ovom slucaju pokazivač u C#-u, da u memoriju smesti objekat klase SqlConnection ili to samo važi za tip podatka, tipa new string, int, float itd?
I ja sam dosta stvari "ispod haube" skontao kada sam se jedan da "igrao" sa Asemblerom...
Bilo je slučajeva i u c#-u gde se moglo koristiti *nesto, ali je moralo da se kastuje ako se ne varam...

Evo googlao sam malo, pa sam skontao sve

"C# also supports pointers in a limited extent. A pointer is nothing but a variable that holds the memory address of another type. But in C# pointer can only be declared to hold the memory address of value types and arrays. Unlike reference types, pointer types are not tracked by the default garbage collection mechanism. For the same reason pointers are not allowed to point to a reference type or even to a structure type which contains a reference type. We can say that pointers can point to only unmanaged types which includes all basic data types, enum types, other pointer types and structs which contain only unmanaged types. "
[ mmix @ 29.10.2012. 09:24 ] @
Citat:
Boyka: Aha, a recimo klasa SqlConnection con = new SqlConnection(); da li je i ona u ovom slucaju pokazivač u C#-u, da u memoriju smesti objekat klase SqlConnection ili to samo važi za tip podatka, tipa new string, int, float itd?


Da. U osnovi nema mnogo velike razlike izmedju C++ koda i C# koda kad odes dovoljno duboko, samim tim instancijacija objekata je funkcionalno ista, svaka klasa ima footprint koji sadrzi vTable i polja i new alocira prostor na heapu, inicijalizuje vTable i poziva konstruktor.

Cela problematika sa referencama i kontrolom istih je zbog GCa. Kad se kod JITuje i spusti na metal rade isto, imas pointer na memorijsku lokaciju koji se smesta u (R/E)?X registar i koristi direktno ili kroz offset (pointer arithmetic).

[ deerbeer @ 29.10.2012. 10:06 ] @
@Boyka
Pricamo o c# referentim tipovima vs C++ pointeri .

To sto si guglao to su ceovski "unsafe pointeri" u C# koji veoma malo imaju veze sa pravim c++ pointerima, i oni su ograniceni dodatak c# kao inline koriscenje c++ koda,
nesto slicno kao u c++-u sto mozes da imas __asm blokove koda ali sa potpunom slobodom koriscenja asemblera .

Tako da , ako ces da ucis o pointerima zaboravi unsafe pointere jer ih tek onda neces nauciti



[ mmix @ 29.10.2012. 10:38 ] @
Gresis, funkcionalno, unsafe C# pointer je apsolutno identican kao C++ pointer i IL ga tako i tretira i nema veze sa asm_blokovima vec sa GC-free blokovima jer mora da se osigura da memorijski blok nece promeniti svoju fizicku adresu u GC ciklusu tokom opeacije, tu je i fundamentla razlika izmedju referenci i pointera i "managed' konteksta. nema tu neke velike mudrosti inace C++/CLI ne bi mogao da postoji.

mada, sa zadnjom recenicom se slazem, problem sa ucenjem pointera na C# je sto ti oni uopste ni ne trebaju jer referenca na metal funkcionise kao C++ pointer, i sto moras namerno da se kacis sa pointerima da bi ih koristio "natively", cisto da bi ih koristio. Samim tim, neces sebi praviti probleme i petljati sa time ako ti ne treba, a retko treba.

Ako hoces da ucis poitnere C/C++ je mesto za to.
[ Nedeljko @ 29.10.2012. 16:23 ] @
Pokazivači su neophodni kad god treba da se radi sa proizvoljnom količinom podataka, tj. koja nije fiksirana u programu. Ako rešavamo zadatak "sortirati niz od najviše 100 celih brojeva", onda nam pokazivači ne trebaju, ali kada podataka može da bude proizvoljan broj, onda su neophodni pokazivači.

Naravno, u nekim slučajevima postoje (vrlo korisne) poštapalice koje u sebi sadrže pokazivače i koriste se umesto sirovih pokazivača. Na primer, tu su klasa string, kao i razni kontejneri. No, to je samo skrivena upotreba pokazivača. Takođe, neki algoritmi za koje je neophodan stek se prividno mogu rešiti bez upotrebe steka - rekurzijom.
[ Boyka @ 29.10.2012. 18:30 ] @
Citat:
Nedeljko: Pokazivači su neophodni kad god treba da se radi sa proizvoljnom količinom podataka, tj. koja nije fiksirana u programu. Ako rešavamo zadatak "sortirati niz od najviše 100 celih brojeva", onda nam pokazivači ne trebaju, ali kada podataka može da bude proizvoljan broj, onda su neophodni pokazivači.

Naravno, u nekim slučajevima postoje (vrlo korisne) poštapalice koje u sebi sadrže pokazivače i koriste se umesto sirovih pokazivača. Na primer, tu su klasa string, kao i razni kontejneri. No, to je samo skrivena upotreba pokazivača. Takođe, neki algoritmi za koje je neophodan stek se prividno mogu rešiti bez upotrebe steka - rekurzijom.
Citat:
mmix: Gresis, funkcionalno, unsafe C# pointer je apsolutno identican kao C++ pointer i IL ga tako i tretira i nema veze sa asm_blokovima vec sa GC-free blokovima jer mora da se osigura da memorijski blok nece promeniti svoju fizicku adresu u GC ciklusu tokom opeacije, tu je i fundamentla razlika izmedju referenci i pointera i "managed' konteksta. nema tu neke velike mudrosti inace C++/CLI ne bi mogao da postoji.

mada, sa zadnjom recenicom se slazem, problem sa ucenjem pointera na C# je sto ti oni uopste ni ne trebaju jer referenca na metal funkcionise kao C++ pointer, i sto moras namerno da se kacis sa pointerima da bi ih koristio "natively", cisto da bi ih koristio. Samim tim, neces sebi praviti probleme i petljati sa time ako ti ne treba, a retko treba.

Ako hoces da ucis poitnere C/C++ je mesto za to.


Skapirao :) Hvala vam...


EDIT

Hajde sada posto sam uradio u podforumu C za pocetnike nekom liku zadatak, da mi objasnite u dole kodu gde sam recimo mogao koristiti pokazivac?

Code (c):

#include "stdafx.h"
#include "stdio.h"

int Rekurzija(int);
int main()
{
     int niz[] = {1,2,3,4,5,6};
     int duzina = sizeof(niz)/sizeof(int);
     printf("%s",niz[Rekurzija(duzina)]);
     getchar();
}

int Rekurzija(int niz)
{
     while(niz!=0)
          return Rekurzija(niz-1);
}


[Ovu poruku je menjao Boyka dana 29.10.2012. u 21:42 GMT+1]
[ Nedeljko @ 30.10.2012. 14:17 ] @
Nemaš izlaz iz rekurzije. Uzmi neki konkretan primer, tj. zadatak o tome šta funkcija treba da radi.