PDA

Tam Sürümünü Görmek İçin : dongu icinde tanimlanmis degiskene deger atama


ceeyt
11/02/2005, 21:52
Bir kitapta asagidaki gibi bir sey gordum ilgimi cekti, "kesinlikle evet" diyemiyorum.Belki derleyiciye gore degisebilir diye dusunuyorum ama emin degilim.

Sizce?

int n = 0;
while(n++ < 30)
{
int i = 10;
/*.............
.............*/
}

Dongu icinde, i ye her seferinde 10 mu atanir?


acehreli
11/02/2005, 23:50
Cok normal... C'de degiskenler "islevlerin basinda" degil, "kapsamlarin basinda" tanimlanirlar zaten. Hemen sen de uygulamaya basla. :)

Anlasilan, o degisken yalnizca while dongusu icinde kullaniliyor; o yuzden onu o kapsamda kisitlamak kodun okunurlugunu arttirir. Tabii aslinda belki de dongunun icerigini baska bir islev olarak yazmak ve boylece o degiskeni de o yeni isleve tasimak cok daha iyi olabilir.

Ayrica, onemsiz bir duzeltme: Aslinda o satirda bir atama (assignment) islemi degil, bir ilk degerleme (initalization) islemi soz konusu.

Ali

acehreli
12/02/2005, 00:06
ceeyt, nedense senin mektuplarini eksik veya yanlis anlama egilimindeyim. :( Sordugun son soruyu gormedigim icin zaten bildigin temel bir kurali tekrarlamisim.

Sorunun yaniti: evet, dongu icinde her seferinde 10 degerinde bir degisken tanimlanir. Eger int yerine daha karmasik bir tur kullanilmissa, her seferinde o nesnenin kurucu islevi cagrilir.

Ali

ceeyt
12/02/2005, 03:25
ceeyt, nedense senin mektuplarini eksik veya yanlis anlama egilimindeyim.

Ben hayatimdan memnunun ama :)

Aklima gelen, i dongu icinde hic degismediginden, derleyici tekrar tekrar deger atamayi engellemek icin, i sanki while dan once ve const tanimlanmis gibi isleme sokabilir mi?

yer yuzunde boyle bir derleyici var midir acaba :)

Volkan Uzun
12/02/2005, 03:38
eger i dongu icinde degismiyorsa
derleyici bunun yerine 10 rakamini koyabilir.
kodun devamina bagli.

Euclides
12/02/2005, 15:24
Ben senin için şunu denedim
Visual C++ 6 (gcc deneyleri daha aşağıda :) )
Not: Programın adı "123" idi...
======================Deney 1======================

int main(int argc, char* argv[])
{
int x;
int n=10;
__asm int 3
while(n>0)
{
x=1234;
n--;
}
printf("%d",x);
return 0;
}

Derleyici "while" döngüsünü TAMAMEM ATLADI !
Sadece printf("%d",1234); komutunu derledi ..

00401001 |. 68 D2040000 PUSH 4D2
00401006 |. 68 30604000 PUSH 123.00406030
0040100B |. E8 10000000 CALL 123.00401020

======================Deney 2======================

int main(int argc, char* argv[])
{
int x;
int n=10;
__asm int 3
while(n>0)
{
x=1234;
printf("%d",x);
n--;
}
return 0;
}

Seninde aşağıda görebileceğin gibi
printf("%d",1234);
şeklinde derliyor.

00401002 |. BE 0A000000 MOV ESI,0A
00401007 |> 68 D2040000 /PUSH 4D2
0040100C |. 68 30604000 |PUSH 123.00406030
00401011 |. E8 0A000000 |CALL 123.00401020
00401016 |. 83C4 08 |ADD ESP,8
00401019 |. 4E |DEC ESI
0040101A |.^75 EB \JNZ SHORT 123.00401007

====================GCC=========================== =
GCC

void main(void)
{
int x;
int n=10;
asm("int $3");
while(n>0)
{
x=1234;
n--;
}
printf("%d",x);
return 0;
}

Aşağıda da görüldüğü gibi gcc gerçekten bir değiken için yer ayırıyor ve bıkmadan usanmadan herseferinde 1234 değerini atıyor.böööööööğğğğğğ

0x0804835c <main+0>: push %ebp
0x0804835d <main+1>: mov %esp,%ebp
0x0804835f <main+3>: sub $0x8,%esp
0x08048362 <main+6>: and $0xfffffff0,%esp
0x08048365 <main+9>: mov $0x0,%eax
0x0804836a <main+14>: sub %eax,%esp
0x0804836c <main+16>: movl $0xa,0xfffffff8(%ebp)
0x08048373 <main+23>: int3
0x08048374 <main+24>: cmpl $0x0,0xfffffff8(%ebp)
0x08048378 <main+28>: jg 0x804837c <main+32>
0x0804837a <main+30>: jmp 0x804838a <main+46>
0x0804837c <main+32>: movl $0x4d2,0xfffffffc(%ebp)
0x08048383 <main+39>: lea 0xfffffff8(%ebp),%eax
0x08048386 <main+42>: decl (%eax)
0x08048388 <main+44>: jmp 0x8048374 <main+24>
0x0804838a <main+46>: sub $0x8,%esp
0x0804838d <main+49>: pushl 0xfffffffc(%ebp)
0x08048390 <main+52>: push $0x8048498
0x08048395 <main+57>: call 0x8048288
0x0804839a <main+62>: add $0x10,%esp
0x0804839d <main+65>: leave
0x0804839e <main+66>: ret

acehreli
12/02/2005, 22:03
Aslinda gcc de yapabilir tabii ama bu isin kontrolunu kullaniciya birakmis.

Genelde -O2 secenegi yeterli olur. Euclides'in verdigi programda -O2 secenegi 1234 degerinin tekrar tekrar atanmasini onledi, ama donguyu tamamen ortadan kaldirmadi:


movl $10, %eax
...
.L4:
decl %eax
testl %eax, %eax
jg .L4


Onu ortadan kaldirmak icin ozellikle -funroll-loops secenegini de vermek gerekti:

gcc -S deneme.c -O2 -funroll-loops

Tabii baska bir programda bu secenek yarardan cok zarar getirebilir. Ornegin dongu ortadan kalktigi icin kod buyuyebileceginden islemcinin on bellegine sigmayabilir.

Bu arada, gcc 3.4.2'nin eniyilestirme ile ilgili seceneklerinin sayisi 94'mus. Yuh! :)

Ali

Euclides
14/02/2005, 09:28
yokmudur bu gcc'nin bir kolayı ?bu derleme işini ayarlayan bir yardımcı program ?