Srodne teme
Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

Ccccc 1

[es] :: C/C++ programiranje :: Ccccc 1

[ Pregleda: 3391 | Odgovora: 8 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

sportbili

Član broj: 5083
Poruke: 16
*.InfoSky.Net



Profil

icon Ccccc 115.09.2002. u 15:21 - pre 262 meseci
Sta se ovde desava?
U nekom clanku na internetu sam nasao sledece

Citat:

26. Under my compiler, the code "int i = 7; printf("%d\n", i++ * i++);"
prints 49. Regardless of the order of evaluation, shouldn't it
print 56?

A: The operations implied by the postincrement and postdecrement
operators ++ and -- are performed at some time after the operand's
former values are yielded and before the end of the expression, but
not necessarily immediately after, or before other parts of the
expression are evaluated.



Code:

int main() {

int a=7;
printf("%d\n", a++ * a++);
printf("%d %d %d\n", a++, a++, a++); // <------
}


Postavila su se dva pitanja. Prvo, tvrdnja iz clanka nije tacna jer dobijam bas
56 sto znaci da je a u drugom izrazu (a++) vec dobila drugu vrednost. Pitanje glasi
da li to zavisi od kompajlera ili neceg drugog? Tekst je iz 1991. znaci nakon ANSI C-a

Drugo se tice printf-a. Kada izvrsim program drugi printf izbacuje
11 10 9
znaci obrnuto od onoga sto sam ocekivao (9 10 11). Zasto?

 
Odgovor na temu

Dragi Tata
Malo ispod Kanade

Član broj: 1958
Poruke: 3906
..g-c5300-1.dialup.nethere.net



+6 Profil

icon Re: Ccccc 115.09.2002. u 23:19 - pre 262 meseci
1. I na mom kompajleru (VC.7.0) izbacuje 49, a to bi i trebalo po standardu. Koji kompajler ti koristiš?

2. Na mom kompajleru, rezultat je 7, 7, 7 a a je 10 posle poziva printf - opet onako kako treba da bude...
 
Odgovor na temu

random
Vladimir Vrzić
Beograd

Član broj: 85
Poruke: 3866
194.106.163.*

Sajt: www.last.fm/user/vrza


+4 Profil

icon Re: Ccccc 116.09.2002. u 00:42 - pre 262 meseci
Jako zanimljivo. GCC će ih takođe ispisati obrnutim redom. Evo odgovarajućeg asm koda:

Code:
movl   $0x7,0xfffffffc(%ebp)  ; snimamo vrednost "7" negde u data segment
; sad se spremamo da pozovemo printf, a parametre stavljamo na stek obrnutim redosledom
mov    0xfffffffc(%ebp),%eax ; treći parametar ide na stek (ono treće a++);
push   %eax ; pa odatle "7" ide na stek
incl   0xfffffffc(%ebp) ; post-inkrementira se treći parametar (sad je 8)
mov    0xfffffffc(%ebp),%eax ; e ovde je caka, jer iz tačke gledišta kompajlera, svi parametri su isti, pa se koristi isti podatak (već post-inkrementiran, iznosi 8)
push   %eax ; "8" ide na stek
incl   0xfffffffc(%ebp) ; ponovo se inkrementira isti taj podatak
mov    0xfffffffc(%ebp),%eax ; i još jednom sve isto, za prvi parametar
push   %eax ; "9" ide na stek
incl   0xfffffffc(%ebp)
push   $0x401040
call   0x401100 <printf>


Na kraju kad printf() pokupi parametre, on ih kupi obruntim redosledom od onog kojim su stavljani (LIFO disciplina), znači prvo 9, pa 8, pa 7. Problem leži u tome što korisnik/programer pretpostavlja da se parametri procesiraju sa leva na desno, što nije slučaj.

Pravo rešenje bi bilo da se naprave posebne kopije svakog parametra u memoriji, bez obzira da li su isti ili ne, a ne da se inkrementira jedan te isti podatak dvaput pri evaluaciji izraza. Dakle problem je kod kompajera.

Zanimljivo je da će ih GCC, čak i kad se specificira -ansi flag, ispisati brojeve obrnutim redosledom. Zaista čudan propust, ako standard kaže drugačije?

Što se prvog pitanja tiče, sa GCC-om sam dobio 49. Provera dibagerom je pokazala da je prvo pomnožio vrednost samu sa sobom, a zatim je dvaput inkrementirao.
int rand(void);

Those who do not understand Unix are condemned to reinvent it, poorly.

Upali lampicu — koristi Jabber!
 
Odgovor na temu

Dragi Tata
Malo ispod Kanade

Član broj: 1958
Poruke: 3906
..ndg-pm4-1.dialup.nethere.net



+6 Profil

icon Re: Ccccc 116.09.2002. u 01:29 - pre 262 meseci
Ako ćemo po asembleru, evo šta uradi VC.NET u release izdanju:

Code:

00401000  push        7    
00401002  push        7    
00401004  push        7    
00401006  push        offset string "%d %d %d\n" (4060ECh) 
0040100B  call        printf (401020h) 
00401010  add         esp,10h 


Dakle, kompajler je dovoljno pametan da zaključi da mu vrednost promenljive ne treba posle štampanja, pa je nije ni povećavao.

U debug verziji:

Code:

00411A2E  mov         dword ptr [a],7 
00411A35  mov         eax,dword ptr [a] 
00411A38  mov         dword ptr [ebp-0D0h],eax 
00411A3E  mov         ecx,dword ptr [a] 
00411A41  add         ecx,1 
00411A44  mov         dword ptr [a],ecx 
00411A47  mov         edx,dword ptr [a] 
00411A4A  mov         dword ptr [ebp-0D4h],edx 
00411A50  mov         eax,dword ptr [a] 
00411A53  add         eax,1 
00411A56  mov         dword ptr [a],eax 
00411A59  mov         ecx,dword ptr [a] 
00411A5C  mov         dword ptr [ebp-0D8h],ecx 
00411A62  mov         edx,dword ptr [a] 
00411A65  add         edx,1 
00411A68  mov         dword ptr [a],edx 
00411A6B  mov         eax,dword ptr [ebp-0D0h] 
00411A71  push        eax  
00411A72  mov         ecx,dword ptr [ebp-0D4h] 
00411A78  push        ecx  
00411A79  mov         edx,dword ptr [ebp-0D8h] 
00411A7F  push        edx  
00411A80  push        offset string "%d %d %d\n" (4240B8h) 
00411A85  call        @ILT+1150(_printf) (411483h) 
00411A8A  add         esp,10h 


U debug verziji je ispisao 9,8,7 , hehehe...

Uglavnom, zanimljiva "gimnastika za mozak", ali najtoplije preporučujem da se ovakve konstrukcije izbegavaju kod ozbiljnog rada.
 
Odgovor na temu

Milan Aksic

Član broj: 412
Poruke: 1053
*.beotel.net



Profil

icon Re: Ccccc 116.09.2002. u 02:05 - pre 262 meseci
I Borlandov kompajler ce ispisati vrednosti na isti nacin.
Inace zanimljivon posle drugog poziva printf-a u VC 6 a je 9, 9, 9, i ovde se postfiksni operater primenjuje u drugom pozivu printf-a od prvog do zadnjeg parametra, i u eventualnom sledecem pozivu postavlja tacnu vrednost 12, a ne od operanda do operanda.
 
Odgovor na temu

sportbili

Član broj: 5083
Poruke: 16
*.dial.InfoSky.Net



Profil

icon Re: Ccccc 116.09.2002. u 03:18 - pre 262 meseci
Citat:

1. I na mom kompajleru (VC.7.0) izbacuje 49, a to bi i trebalo po standardu. Koji kompajler ti koristiš?


Borland C/C++ 3.1 Compiler :-)

Matoro ali sluzi. Nego trazio sam po netu tutoriale za asm za pocetnike
pa ako neko zna neki, link bi dobro dosao (ja sam nasao neke ali
mozda imate preporuku?)

Pozdravi
 
Odgovor na temu

sspasic
Sasa Spasic

Član broj: 3261
Poruke: 175
*.medianis.net

Jabber: sspasic@elitesecurity.org
ICQ: 35454521


Profil

icon Re: Ccccc 116.09.2002. u 18:06 - pre 262 meseci
Tu je ispravan odgovor (po ansi) 49 ili 56, zavisno od implementacije.
C za sve operatore (sem || i &&) ne odredjuje redosled kojim se podizrazi izracunavaju.
Jedino sto garantuje kod i++ je da ce se vrednost uvecati POSLE izracunavanja vrednosti i (ali ne mora odmah posle), a ne posle izracunavanja vrednosti i++ * i++.

Slicno vazi i za redosled izracunavanja parametara u pozivu funkcije.

Pogledajte K&R, poglavlje 2.2
 
Odgovor na temu

Rapaic Rajko
Bgd

Član broj: 4105
Poruke: 810
*.beg.sezampro.yu



+62 Profil

icon Re: Ccccc 116.09.2002. u 20:51 - pre 262 meseci
Ja, iskreno, nisam toliko dobar poznavalac standarda, ali po nekoj logici, trebalo bi da ispravan rezultat bude 49. Razmislite, sta je logicno u sledecem slucaju?

int a=7, b=7;
printf("%d\n",a++ * b++);

Ocigledno je (bar meni) jedini ispravan rezultat 49. Nazalost, izgleda da moj kompajler (CBuilder) ne misli tako.

Rajko
 
Odgovor na temu

Dragi Tata
Malo ispod Kanade

Član broj: 1958
Poruke: 3906
199.171.112.*



+6 Profil

icon Re: Ccccc 116.09.2002. u 21:02 - pre 262 meseci
Kao što već napomenuh, pitanje je od čisto akademskog značaja. U praksi, printf("%d\n",a++ * b++); i slične egzibicije se smatraju lošim kodom i treba ih izbegavati po svaku cenu. Nikakve koristi od toga, a kod je nečitljiv, teško ga je debugovati, a da i ne pominjem da razni kompajleri (ili čak isti sa promenjenim opcijama za optimizaciju) različito izvršavaju takve instrukcije, kao što se da videti iz prethodnih postova. Jednostavno, batalite to...

 
Odgovor na temu

[es] :: C/C++ programiranje :: Ccccc 1

[ Pregleda: 3391 | Odgovora: 8 ] > FB > Twit

Postavi temu Odgovori

Srodne teme
Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.