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
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
Offline

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)
Offline
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

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ě
Offline
↑ 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é. :-)
Offline

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)
Offline
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