Matematické Fórum

Nevíte-li si rady s jakýmkoliv matematickým problémem, toto místo je pro vás jako dělané.

Nástěnka
22. 8. 2021 (L) Přecházíme zpět na doménu forum.matweb.cz!
04.11.2016 (Jel.) Čtete, prosím, před vložení dotazu, děkuji!
23.10.2013 (Jel.) Zkuste před zadáním dotazu použít některý z online-nástrojů, konzultovat použití můžete v sekci CAS.

Nejste přihlášen(a). Přihlásit

#1 05. 01. 2012 17:00

Babuna18
Zelenáč
Příspěvky: 10
Reputace:   
 

Zadani algoritmu

Zdravím, mohl bych vás tu někoho poprosit o radu, jak se řeší takový příklad? Trošku mám problémy s těmi adresami proměnných. Nechci po vás řešení, jen nějaké vyvsvětlení, jak se to řeší. Vyřešit to zkusím sám a pak bych někoho z vás poprosil o kontrolu. Moc díky


http://forum.matweb.cz/upload3/img/2012-01/79202_prog.jpg

Offline

  • (téma jako vyřešené označil(a) frank_horrigan)

#2 05. 01. 2012 17:13 — Editoval frank_horrigan (05. 01. 2012 17:20)

frank_horrigan
Příspěvky: 938
Reputace:   31 
 

Re: Zadani algoritmu

Ahoj,
představ si to asi takto:

int i, j, k - to jsou "nějaké" proměnné uložené v "nějaké" paměti. K té "nějaké paměti se dostaneš přes operátor reference & . Na tyto proměnné můžeš aplikovat jakékoli matematické operace (tedy i^j, za předpokladu, že jsou inicializované, tedy mají hodnotu) ti to vrátí správný výsledek. Nesmysl je ale příkaz (&i)^(&j) (k čemu je dobré umocňovat ukazatel, že?)

Naopak int *ip je ukazatel, tedy ten vlastně sám o sobě nese hodnotu adresy paměti (tedy stejný nesmysl je zápis pi^i (třeba)). K hodnotě, na kterou ten ukazatel ukazuje, se dostaneš přes operátor dereference *.

Tedy příklad (jiný)

int i = 20;
int *pi = 10;

A výstup bude i = 20, &i = 0x04F4FFFA, pi = 0x04F4E210, *pi = 10, i + (*pi) = 30, i+ pi = (nesmysl, buď nesmyslný výsledek, nebo warn, možná i chyba překladu (dle verze a druhu překladače)

Pochopil jsi z toho něco?

EDIT: samozřejmě můžeš taky vyvádět zvěrstva jako &pi, to ti potom vrátí adresu, kde sedí ukazatelová proměnná (která má u dnešních "klasických" ukazatelů 32 bitů) - ovšem adresa ukazatele (nebo ukazatel na ukazatel) ti ve většině případů není k ničemu dobrá

EDIT2: jestli to musíš nebo chceš udělat i s průběžnými hodnotami proměnných uvnitř programu (a tím si vlastně uvědomíš, jak to funguje, tak se o to můžeš pokusit, kdyžtak ti najdeme chybu v postupu také :)

EDIT3: a jestli jsi rýpavý a šťouravý (což by správný programátor měl být), můžeš upozornit zadavatele, že tenhle kód, který jsi dal, nepůjde přeložit (main() by měla mít uvedený návratovej typ, v tomto případě stačí void)


The only thing worse than being wrong is staying wrong
Sun Tzu - The Art of War

Offline

 

#3 05. 01. 2012 18:14

Babuna18
Zelenáč
Příspěvky: 10
Reputace:   
 

Re: Zadani algoritmu

Takže například v tom mým příkladu, když mám ip=&i tak mi to do ip uloží adresu i? a potom když zadám do i=20 a zadám j=*ip, tak mi to do j uloží hodnotu co je na adrese ip, což je vlastně adresa i a mělo by to tedy být že j=20. Napsal jsem to asi trochu nepřehledně, takže nevím jestli je to z toho pochopit

Offline

 

#4 05. 01. 2012 18:16

Babuna18
Zelenáč
Příspěvky: 10
Reputace:   
 

Re: Zadani algoritmu

Takže vlastně celkový výsledek toho příkladu by byl j = 20, k = 21 , i = 16 ?

Offline

 

#5 05. 01. 2012 18:42 — Editoval frank_horrigan (05. 01. 2012 18:43)

frank_horrigan
Příspěvky: 938
Reputace:   31 
 

Re: Zadani algoritmu

jj, přesně tak... a když změníš hodnotu i, tak se ti změní i hodnota *pi, protože ukazuje na stejnou adresu kde je i. Takže výsledky máš správně, můžeš si to zkusit nabušit, přeložit (nezapomeň na ten návratový typ main), a dostaneš totéž - a když budeš krokovat v debuggeru, tak dostaneš níže uvedený postup:

krok po kroku:

1)deklarace proměnných, všechny čtyři dostanou nějakou adresu, *ip nemá smysl, na té adrese je nějaký bordel
2) ip dostane hodnotu i, ve které je taky bordel, takže *ip stále nemá smysl
3) i = 20, ip ukazuje kde je i, takže *ip vrátí také 20
4) operátor rovnosti je asociativní zprava, takže nejdříve se vyhodnotí *ip (20), a to se přiřadí j (j bude 20)
5) opět, se vyhodnotí pravá strana, *ip + 1, a výsledek (21) s edá do k
6) s adresou ip se nic nedělá, takže stále je na ní uložená hodnota 20, *ip - 4 = 16, i bude rovno 16, a *ip bude také mít hodnotu 16 (po provedení příkazu)

Takže to máš správně


The only thing worse than being wrong is staying wrong
Sun Tzu - The Art of War

Offline

 

#6 05. 01. 2012 18:58

Babuna18
Zelenáč
Příspěvky: 10
Reputace:   
 

Re: Zadani algoritmu

To mám upřímnou radost, protože to vypadalo ze začátku trochu složitě.

Takže když budu mít kod:

int a=5 , b=10;
int *p, *q;
p = &a;
q = &b;
*p = b + *q;
p = q;
*q = b + *p;
b = a + 3;


takže potom bude: a = 5, b = 8, *p = 20, *q = 30   ??

Offline

 

#7 06. 01. 2012 01:03 — Editoval RePRO (06. 01. 2012 01:17)

RePRO
Místo: Jihlava
Příspěvky: 363
Škola: AI VŠPJ (09-12, Bc.)
Pozice: programátor
Reputace:   11 
Web
 

Re: Zadani algoritmu

↑ Babuna18:

Zdravím :-),
koukněmě na to tak, jak je to opravdu v paměti:

Proč tomu tak je (vždycky je třeba vědět, kam který ukazatel ukazuje):
int a=5 , b=10;
int *p, *q;

// ukazatel p má v sobě adresu a (ukazuje na adresu a)
p = &a;

// ukazatel q má v sobě adresu b (ukazuje na adresu b)
q = &b;

// nastavíme ukazateli p hodnotu (10+10 = 20), ale tím i změníme proměnnou a na hodnotu 20, protože tam ukazuje ukazatel p
*p = b + *q;

// teď nastavíme, že p bude ukazovat tam, kam ukazuje q... a kam ukazuje q? ukazuje na b
// takže ukazatel p i q teď ukazují na b (oba ukazatele drží hodnotu proměnné b, což je 10)
p = q;

// do ukazatele se nastaví hodnota (10+10 = 20) a jelikož tam ukazuje i p tak ten taky + se změní proměnná b na hodnotu 20
*q = b + *p;

// a nastavíme do proměnné b = 20 + 3 = 23 (ale nezapomeňme, že na b ukazují jak ukazatel p, tak q :-) )
b = a + 3;

Bude to (myslím) takto:
a = 20, b = 23, *p = 23, *q = 23

Snad je to dosti srozumitelné. :-)


Srdcem trochu-programátor, duší rádoby-matematik a povoláním analytik-vývojář.

Offline

 

#8 08. 01. 2012 11:44

Babuna18
Zelenáč
Příspěvky: 10
Reputace:   
 

Re: Zadani algoritmu

Aha, tak jsem to pochopil trochu jinak...tak teď už snad správně.

Takže tady:

http://forum.matweb.cz/upload3/img/2012-01/19347_uk.jpg

takže mi vyšlo : ii = -84, nn = -76, *qq = -76, *uu = -76

je to správně?

Offline

 

#9 08. 01. 2012 13:16 — Editoval frank_horrigan (08. 01. 2012 13:32)

frank_horrigan
Příspěvky: 938
Reputace:   31 
 

Re: Zadani algoritmu

Mně vyšlo ii = -84, nn = -172, *qq = -172 a *uu = -172, a (to jsi v zadani opomnel), qq bude mit stejnou adresu jako uu)
EDIT: po opravě ii = -84, nn = -166, *qq = -166, *uu = -166 (a to je správně, kontrolováno výstupem skutečného programu)

Pojedeme po řádcích:
int nn, ii, *uu, *qq; //nn = junk, ii = junk, *qq = junk, *uu = junk
uu = ⅈ // ukazetel uu ukazuje na ii
qq = &nn; // qq ukazuje na nn
*uu = -62; //protoze uu ukazuje na ii, tak zmenime hodnotu promenne ii pomoci ukazatele, nyni *uu = ii = -62
*qq = -88; // totez z druhou promennou, bude *qq = nn = -88

uu = qq; // tady asi delas chybu - ukazatel uu obsahuje tu samou adresu, co obsahuje qq, takze mas *uu = *qq = nn = -88

ii = *uu + 4; // na *uu mas ulozene cislo -88, hodnota ii = -84 (a na ii jiz neukazuje zadny ukazatel)
nn = *qq +6; // na *qq je ta sama hodnota jako na *uu (ukazuji na stejnou promennou nn), takze vysledek -82
*qq = *uu + ii; // tady jsou dva kroky - na *uu je -88, ii nese hodnotu -84, tedy vysledek je -172, a pozor, jeste se ti zmeni promenna na kterou qq ukazuje, tedy nn, a zaroven i ukazatel uu, ktery take ukazuje na nn

Tady je presne videt, jak jsou pointery nebezpecne a proc vetsina lidi nema rada cecko.

Ještě prosím kolegy o kontrolu mého postupu (nebo zkus najít sám chybu, pokud jsem tam nějakou udelal), než to vezmeš za správné

EDIT: dal jsem si to do kódu, někde mám numerickou chybu, vychází mi -166, namísto -172 u těch tří
Když už jsem ti dal postup, zkus jí najít (já už jí vidím)


The only thing worse than being wrong is staying wrong
Sun Tzu - The Art of War

Offline

 

#10 08. 01. 2012 14:03

Babuna18
Zelenáč
Příspěvky: 10
Reputace:   
 

Re: Zadani algoritmu

JJ, postup jsem měl správný a chybu jsem měl v posledním řádku kde jsem přehlédl jedno minusové znaménko..takže to vypadá, že jsem to snad pochopil dobře :) každopádně díky moc za další vysvětlení, u kterého jsem si tak nějak ověřil, že to chápu :) díky moc!

Offline

 

Zápatí

Powered by PunBB
© Copyright 2002–2005 Rickard Andersson