Jump to page: 1 2
Thread overview
Switch Case D'de nasıl çalışıyor?
Jan 12, 2013
Salih Dinçer
Jan 12, 2013
Salih Dinçer
Apr 24, 2013
Salih Dinçer
Apr 24, 2013
Salih Dinçer
Apr 25, 2013
Salih Dinçer
Apr 25, 2013
Salih Dinçer
Apr 25, 2013
Salih Dinçer
January 12, 2013

Merhaba,

Buna benzer bir çalışma daha önce yapmıştım. Programlama dünyasında biliriz ve hep deriz ki switch case hızlıdır. Ancak daha önce hatırladıklarımdan, assembly karşılığı alt alta if()'leri sıralamaktan farkı olmadığını görmüştüm. Tabi buna etken şeyler olabilir. Beliki (sanrım sadece D'de olan?) final takısını koyduğumuzda default sekmesine gerek olmadığı için üretilen assembly kodu değişebilir. Bunu birlikte göreceğiz...:)

Şimdi küçük bir hafta sonu çalışmasına yayacağımız koda geçelim:

void main() {
 int seç, sonuç;

 asm {
   pop EBX;
   mov seç[EBP], EBX;
   push EBX;
 }
 switch(seç) {
   case 0: sonuç = 0; break;
   case 1: sonuç = 1; break;
   case 2: sonuç = 2; break;
   case 3: sonuç = 3; break;
   case 4: sonuç = 4; break;
   case 5: sonuç = 5; break;
   case 6: sonuç = 6; break;
   case 7: sonuç = 7; break;  // benim bilgisayarımda yığından, nedense 7 sonucu alınıyor...:)
   case 8: sonuç = 8; break;
   case 9: sonuç = 9; break;
   default:
 }
}

Bunu neden böyle yapıyorum çünkü an itibariyle Dpaste (http://dpaste.dzfl.pl/)'ye giremiyorum! İstiyorum ki diğer D derleyicileri ile güzel bir kıyas olsun. Ama henüz kendi bilgisayarımdaki obj2asm ile idare etmeliyim.

Özetle sonuçlar pek yakında ve aşama aşama nakledeceğim...

Başarılar...

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

January 12, 2013

Sanırım kodu değiştirmeliyim çünkü dikkat çekmek istediğim konuya faydası yok:

import std.stdio;

void main() {
   char test = ' ';
   final switch (test) {
       case ' ': case '\t': case '\f': case '\r': case '\n': case '\v':
           writeln("boşluk");
           break;
   }

   auto değer = test;
   if ((değer == ' ') || (değer == '\t') || (değer == '\f') ||
       (değer == '\r') || (değer == '\n') || (değer == '\v'))
       writeln("boşluk");
}

Kaynak: http://ddili.org/forum/post/5007

Nedenini ise kısaca izah edeyim. İlk örnekte gibi basit bir switch-case formu kullanılırsa, assembly kodunda look-up table oluştuğunu gördüm. Bu öyle bir şey ki; özellikle veri kesinlikle eşleşmiyorsa hooop default satırına çok hızlı şekilde atlıyor. Eşleşiyor ise ilgili satıra atlanıyor ve orada ilgili kodlar işletiliyor:

		mov	EAX,-8[EBP] ; // seç değişkeninin adresi
		mov	EDI,offset FLAT:.rodata[019h]@SYM32 ; // look-up table
		mov	ECX,0Ah ; // kaç adetlik veri olduğuna ifade eden sayaç
		repne ; // bir döngü icra ediyor (repeat instruction), sayaçı (ECX) düşürüyor ve
		scasd ; // yazmaçtaki Zero bayrağına bakıyor
		// Yukarıdaki son komut ise look-up table ve aşağıdaki case ... : karşıkları eşeleştirliyor
		jne	L81 ; // default: satırına, bir bakıma switch dışına dallanıyor...
		:		:		: (ikişer satırdan oluşan case ... : karşılıkları)

İki bölümden oluşan look-up table ise dallanacak adres ve veri şeklinde derlenmiş. İşte rodata bölümü:
Alıntı:

>

db 000h,000h,000h,000h,001h,000h,000h,000h ;........
db 002h,000h,000h,000h,003h,000h,000h,000h ;........
db 004h,000h,000h,000h,005h,000h,000h,000h ;........
db 006h,000h,000h,000h,007h,000h,000h,000h ;........
db 008h,000h,000h,000h,009h,000h,000h,000h ;........
dd offset FLAT:_Dmain[029h]@SYM32
dd offset FLAT:_Dmain[032h]@SYM32
dd offset FLAT:_Dmain[03Bh]@SYM32
dd offset FLAT:_Dmain[044h]@SYM32
dd offset FLAT:_Dmain[04Dh]@SYM32
dd offset FLAT:_Dmain[056h]@SYM32
dd offset FLAT:_Dmain[05Fh]@SYM32
dd offset FLAT:_Dmain[068h]@SYM32
dd offset FLAT:_Dmain[071h]@SYM32
dd offset FLAT:_Dmain[07Ah]@SYM32

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

January 12, 2013

İlk başta switch case yapısını neden incelediğinizi anlayamamıştım ama şimdi fark ettim fikir dahice.

Dediğiniz gibi yapılacak olan switch case yapısında kullanılan methodla aynı olacak.

Zekeriya

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

January 12, 2013

C'de 'final switch' olmadığı için onu karşılaştıramayız ama okuduklarıma göre gdc ve ldc dmd'den genelde daha hızlı kod üretiyormuş.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

January 14, 2013

Alıntı:

>

Bunu neden böyle yapıyorum çünkü an itibariyle Dpaste'ye giremiyorum! İstiyorum ki diğer D derleyicileri ile güzel bir kıyas olsun.

http://dpaste.1azy.net/

Açıklama: http://forum.dlang.org/thread/tfzdtbzuilctqnzyonzw@forum.dlang.org

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

January 14, 2013

Bu dpaste harikaymış :) Kodları derlediğini bilmiyorum.

Sitenin kaynak kodlarını inceleyeyim işime yarar :)

Zekeriya

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

April 24, 2013

Görebildiğim ve ilk defa öğrendiğim (veya yanlış bir şey yapıyorum) kadarıyla...

:)

case kümeleri içerisinde başka bir işleve dallanmak/çağırmak olmuyor. Hatta bir nesnenin kurucu üyesi de bir işleve dallanmak olduğu için o da çalışmıyor. O yüzden şurada (http://ddili.org/forum/post/9253) tartışmaya başladığım konuyu ve aşağıda örneği geliştirerek devam ettirdiğimde bu sonuçları aldım:

import std.stdio;

 class A {
   this() {
     writeln("- A sınıfı kurucusundayım...");
   }
   override
   string toString() const {
     return "A SINIFI";
   }
 }

 class B {
   this() {
     writeln("- B sınıfı kurucusundayım...");
   }
   override
   string toString() const {
     return "B SINIFI";
   }
 }

void main(string[] arg) {
 A bir;
 B iki;

 void aKur() {
   writeln("- akur() işlevindeyim...");
   bir = new A();
 }

 void bKur() {
   writeln("- bkur() işlevindeyim...");
   iki = new B();
 }

 int birRakam;
 char seçenekler = arg.length > 1 ? arg[1][0] : 0;
 switch(seçenekler) {
   case  0:
            writeln("pARAMETRE KULLANILMALI");
            birRakam = 1;
            break;
   case  1: aKur(); goto default;
   case  3: aKur();
   case  2: bKur();
   default: writefln("%s, %s", bir, iki);
 }
 writeln(birRakam);
 bir = new A();
 iki = new B();
}

Alıntı ("ÇIKTISI"):

>

'./testcase 3
null, null
0

  • A sınıfı kurucusundayım...
  • B sınıfı kurucusundayım...

./testcase
pARAMETRE KULLANILMALI
1

  • A sınıfı kurucusundayım...
  • B sınıfı kurucusundayım...'

Dip Not: DMD'nin 2.047'ye kadar eski sürümlerinde denedim. Hatta linker hatası almasaydım 2.008'de de deneyecektim. Son sürüm ile alakalı olmayan, dili etkileyen bir kaide var ama ben yeni öğreniyorum! Sanırım programcılık tarihinde böyle bir şey varmış..:)

Ali hocam bizi aydınlatacağını umuyorum...

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

April 24, 2013

Şimdi farkettim, ciddi bir hata yapmışım...:)

Meğer, rakamların ASCII karşlığını kullanmıyormuşum. Doğrusu şu şekilde:

void main(string[] arg) {
 A bir; B iki;
 char seçenekler = arg.length > 1 ? arg[1][0] : 0;

 switch(seçenekler) {
   case  0: writeln("Bir rakam girin..."); break;
   case 49: bir = new A(); goto default;  // 1 rakamı
   case 51: bir = new A();                // 3 rakamı
   case 50: iki = new B();                // 2 rakamı
   default: writefln("%s, %s", bir, iki);
 }
}

Alıntı (ÇIKTISI):

>

'[atelyeweb@sdb tmp]$ ./as 1
A SINIFI, null
[atelyeweb@sdb tmp]$ ./as 2
null, B SINIFI
[atelyeweb@sdb tmp]$ ./as 3
A SINIFI, B SINIFI
[atelyeweb@sdb tmp]$ ./as 4
null, null
'

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

April 25, 2013

Alıntı (acehreli):

>

0, 1, vs. gibi bir numara kullanacaksaz size_t veya int uygundur.
İşte bu durum std.conv'u kullanmak gerektirdiği için ek şeylerden kaçınmak istiyorum:

 int seçenekler = arg.length > 1 ? to!int(arg[1]) : 0;

Ali hocamdan başka bir switch case yorumu:
Alıntı (acehreli):

>

...hatalara açık bir durumdur çünkü bazen devam edilmesi istenmediği halde break deyimi unutulduğu için devam edilir. Güvenliğe önem veren D bu durumu değiştirdi ve ne istediğini programcının açıkça belirtmesini şart koşmaya başladı.

Sanırım hiç kimsenin itiraz etmediği olumlu bir değişiklik oldu...
Teşekkürler, al bir ilginçlik daha...:)

Aslında 2.062 çıktığında bundan bahsedildiğini, yani goto'ların kullanılabileceğini hatırlıyorum. Ancak bunun zorunlu olduğunu bilmiyordum. Yani bir alt satıra (case'e) geçmesi için goto şart mı? Yoksa geçmemesi için break şart mı?

Sanırım her ikisi de değil, sadece biri olmalı. Bu durumda break kullanma zorunluluğu kalkmış, kullanılmadığında break varmış gibi algılanıyor olabilir mi? Ay kafam karıştı şimdi...:)

Çözerim ama 1-2 denemeyle...haha

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

April 25, 2013

Geçen gün gördüğümde dilimin ucuna gelmişti ama kendi tutmuştum. :) Hatırlamakta yarar var: char türünü yalnızca UTF-8 kodu olarak kullanalım. Dolayısıyla, Unicode ile işimiz yoksa char'la da olmamalı.

0, 1, vs. gibi bir numara kullanacaksaz size_t veya int uygundur.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

« First   ‹ Prev
1 2