Switch case mi if else mi?

İlk attığın linkte switch case bloğunun çalışma zamanı tartışılmış ve en kötü durumda lineer zaman karmaşıklığına sahip olduğu söylenmiş. Devamında ise derleyicinin derlenen koda göre bazı optimizasyonlar yapabileceğinden bahsediliyor. İşte bu optimizasyonlardan en aşikarı switch-case deki expression'ın değerinin bilindiği durumda kodun direkt ilgili case aktarılması. Benzer optimizasyon if blokları içinde yapılabilir. Bu switch-case derleme zamanında değerlendirilir ya da çalıştırılır anlamına gelmez.

İkinci linkte ise switch-case de değerlendirilecek ifadenin (expression) tam sayı tipinde olması gerektiği anlatılıyor. Yani int, long ya da short gibi tamsayı tipte olmalı. Ayrıca case yanındaki ifadelerin (constant-expression) değerleri de program çalışmadan derleme aşamasında önceden bilinebilir olmalı. Yani bir literal ya da enum gibi.
 
@Bay şükür, çeviriye ihtiyaç duymayacak durumdayım. Verdiğiniz bilgiyi ve çok daha fazlasını siz vermeden önce biliyordum. Belki bir şekilde savınızı savunursunuz diye düşünüp kısa kesmiştim. Oradaki işlemin switch ile alakası yok. Switch'in güzelliği eşitlik kontrolü yapması. Bir de lineer olması. If kullanırsanız büyüklük kıyaslayabilirsiniz. Birden fazla koşula dayandırabilirsiniz. Özünde switch'te bu yok. Bu yüzden çok daha rahat şekilde jump table hazırlanabiliyor.

Düzgün bir derleyici derleme zamanında değeri kesin olan şeyleri hazırlar ve ona göre optimize eder. Gidip bir sayıya elle 1 atıyor sonra da o sayı 1 ise şunu yap diyorsanız düzgün derleyici direkt o işi yapar. Hatta o yaptığınız iş sonrasında hiç kullanmayacağınız bir değişkenin değerini değiştirmek gibi aslında hiçbir işe yaramayan bir şey ise onu bile yapmaz. Yok sayar. Boşa iş yapmanın anlamı yok.
 
Yahu yanlış bilgi cezası alacaksınız bari güzel bir şey sallayın da değsin.

Switch case içerisinde pin 9 u okuyacak olursam bu derleyiciye gelecek zaman vahiy mi inecek de ona göre derleyecek.

Sizin dediğinize göre ya derleyiciye vahiy iniyor yada switch case program çalışırken değişebilecek bir değişken üzerinde kullanılamıyor. Düşündürücü...
 
Sizin dediğinize göre ya derleyiciye vahiy iniyor yada switch case program çalışırken değişebilecek bir değişken üzerinde kullanılamıyor. Düşündürücü...
Ben kendi yaşadığım tecrübeden yola çıkarak cevap yazmıştım. Stm32 ile switch case yapısı kullanırken kodda derleme hatası olmadı ama switch case yapısı yüzünden kod doğru çalışmadı, mantık hatası oluşmuştu. Amacım fonksiyona girilen değerden yola çıkarak Timerları ayrı ayrı konfigüre etmekti. Sonrasında başka bir arkadaşıma danışarak bu bilgiyi öğrenmiştim. Switch-case yapısını if else yapısına değiştirmemi önermişti. Sorunu bu şekilde halletmişitm. Sanırım benim yaşadığım durum biraz daha spesifik bir durumdu. Eski kod şuan elimde olmadığından size sorunu gösteremiyorum. Saygılar.
 
Yazdıklarına tam olarak katılmakla beraber hem kendimin pekiştirmesi için hem de soruyu soran arkadaşa bir cevap olması için şunu eklemek isterim.
switch-case'in kullanım durumlarını bir küme, if bloklarınınkini ayrı bir küme olarak düşünürsek switch-case if bloklarının bir alt kümesi olmuş oluyor. Yani switch-case ile yazılan kodu if ile aynen yazabiliriz. Fakat if blokları ile yazılmış bir kpdu switch-case ile yazamayabiliriz. if in amacı daha genel, switch-case in daha spesifik bir kullanım sunması.
 
Bir ek daha yapayım.

Aynı assembly karşılaştırmasını direkt olarak Arduino IDE ile gelen avr-gcc compilerıyla da yaptığımda çok benzer sonuçlar elde ediyorum. Bu sefer hem -O3 hem de -Os flagleriyle denedim, çıkan sonuçları buraya atayım.

Compiler komutları şu şekilde:
  1. ./avr-gcc -c -g -O3 -w -std=gnu++11 -fpermissive -lstd -o t1 test.c
  2. ./avr-gcc -c -g -Os -w -std=gnu++11 -fpermissive -lstd -o t1 test.c
Kod:
00000000 <my_func>:
   0:    cf 93           push    r28
   2:    df 93           push    r29
   4:    00 d0           rcall    .+0          ; 0x6 <my_func+0x6>
   6:    cd b7           in    r28, 0x3d    ; 61
   8:    de b7           in    r29, 0x3e    ; 62
   a:    80 e0           ldi    r24, 0x00    ; 0
   c:    90 e0           ldi    r25, 0x00    ; 0
   e:    9f 93           push    r25
  10:    8f 93           push    r24
  12:    00 d0           rcall    .+0          ; 0x14 <my_func+0x14>
  14:    9d 2f           mov    r25, r29
  16:    8c 2f           mov    r24, r28
  18:    01 96           adiw    r24, 0x01    ; 1
  1a:    9f 93           push    r25
  1c:    8f 93           push    r24
  1e:    80 e0           ldi    r24, 0x00    ; 0
  20:    90 e0           ldi    r25, 0x00    ; 0
  22:    9f 93           push    r25
  24:    8f 93           push    r24
  26:    00 d0           rcall    .+0          ; 0x28 <my_func+0x28>
  28:    89 81           ldd    r24, Y+1    ; 0x01
  2a:    9a 81           ldd    r25, Y+2    ; 0x02
  2c:    0f 90           pop    r0
  2e:    0f 90           pop    r0
  30:    0f 90           pop    r0
  32:    0f 90           pop    r0
  34:    0f 90           pop    r0
  36:    0f 90           pop    r0
  38:    86 39           cpi    r24, 0x96    ; 150
  3a:    91 05           cpc    r25, r1
  3c:    01 f0           breq    .+0          ; 0x3e <my_func+0x3e>
  3e:    84 3f           cpi    r24, 0xF4    ; 244
  40:    21 e0           ldi    r18, 0x01    ; 1
  42:    92 07           cpc    r25, r18
  44:    01 f0           breq    .+0          ; 0x46 <my_func+0x46>
  46:    84 36           cpi    r24, 0x64    ; 100
  48:    91 05           cpc    r25, r1
  4a:    01 f0           breq    .+0          ; 0x4c <my_func+0x4c>
  4c:    01 97           sbiw    r24, 0x01    ; 1
  4e:    0f 90           pop    r0
  50:    0f 90           pop    r0
  52:    df 91           pop    r29
  54:    cf 91           pop    r28
  56:    08 95           ret
  58:    87 e6           ldi    r24, 0x67    ; 103
  5a:    90 e0           ldi    r25, 0x00    ; 0
  5c:    0f 90           pop    r0
  5e:    0f 90           pop    r0
  60:    df 91           pop    r29
  62:    cf 91           pop    r28
  64:    08 95           ret
  66:    86 ef           ldi    r24, 0xF6    ; 246
  68:    91 e0           ldi    r25, 0x01    ; 1
  6a:    0f 90           pop    r0
  6c:    0f 90           pop    r0
  6e:    df 91           pop    r29
  70:    cf 91           pop    r28
  72:    08 95           ret
  74:    87 e9           ldi    r24, 0x97    ; 151
  76:    90 e0           ldi    r25, 0x00    ; 0
  78:    0f 90           pop    r0
  7a:    0f 90           pop    r0
  7c:    df 91           pop    r29
  7e:    cf 91           pop    r28
  80:    08 95           ret

Kod:
00000000 <my_func>:
   0:    cf 93           push    r28
   2:    df 93           push    r29
   4:    00 d0           rcall    .+0          ; 0x6 <my_func+0x6>
   6:    cd b7           in    r28, 0x3d    ; 61
   8:    de b7           in    r29, 0x3e    ; 62
   a:    80 e0           ldi    r24, 0x00    ; 0
   c:    90 e0           ldi    r25, 0x00    ; 0
   e:    9f 93           push    r25
  10:    8f 93           push    r24
  12:    00 d0           rcall    .+0          ; 0x14 <my_func+0x14>
  14:    9d 2f           mov    r25, r29
  16:    8c 2f           mov    r24, r28
  18:    01 96           adiw    r24, 0x01    ; 1
  1a:    9f 93           push    r25
  1c:    8f 93           push    r24
  1e:    80 e0           ldi    r24, 0x00    ; 0
  20:    90 e0           ldi    r25, 0x00    ; 0
  22:    9f 93           push    r25
  24:    8f 93           push    r24
  26:    00 d0           rcall    .+0          ; 0x28 <my_func+0x28>
  28:    89 81           ldd    r24, Y+1    ; 0x01
  2a:    9a 81           ldd    r25, Y+2    ; 0x02
  2c:    0f 90           pop    r0
  2e:    0f 90           pop    r0
  30:    0f 90           pop    r0
  32:    0f 90           pop    r0
  34:    0f 90           pop    r0
  36:    0f 90           pop    r0
  38:    86 39           cpi    r24, 0x96    ; 150
  3a:    91 05           cpc    r25, r1
  3c:    01 f0           breq    .+0          ; 0x3e <my_func+0x3e>
  3e:    84 3f           cpi    r24, 0xF4    ; 244
  40:    21 e0           ldi    r18, 0x01    ; 1
  42:    92 07           cpc    r25, r18
  44:    01 f0           breq    .+0          ; 0x46 <my_func+0x46>
  46:    84 36           cpi    r24, 0x64    ; 100
  48:    91 05           cpc    r25, r1
  4a:    01 f0           breq    .+0          ; 0x4c <my_func+0x4c>
  4c:    01 97           sbiw    r24, 0x01    ; 1
  4e:    0f 90           pop    r0
  50:    0f 90           pop    r0
  52:    df 91           pop    r29
  54:    cf 91           pop    r28
  56:    08 95           ret
  58:    86 ef           ldi    r24, 0xF6    ; 246
  5a:    91 e0           ldi    r25, 0x01    ; 1
  5c:    0f 90           pop    r0
  5e:    0f 90           pop    r0
  60:    df 91           pop    r29
  62:    cf 91           pop    r28
  64:    08 95           ret
  66:    87 e9           ldi    r24, 0x97    ; 151
  68:    90 e0           ldi    r25, 0x00    ; 0
  6a:    0f 90           pop    r0
  6c:    0f 90           pop    r0
  6e:    df 91           pop    r29
  70:    cf 91           pop    r28
  72:    08 95           ret
  74:    87 e6           ldi    r24, 0x67    ; 103
  76:    90 e0           ldi    r25, 0x00    ; 0
  78:    0f 90           pop    r0
  7a:    0f 90           pop    r0
  7c:    df 91           pop    r29
  7e:    cf 91           pop    r28
  80:    08 95           ret

Opt level flagi bu compiler'da da -O3'ken elimize geçen tüm instruction'lar tamamen aynı.
Şimdi gelelim -Os flagine.

Kod:
00000000 <my_func>:
   0:    cf 93           push    r28
   2:    df 93           push    r29
   4:    00 d0           rcall    .+0          ; 0x6 <my_func+0x6>
   6:    cd b7           in    r28, 0x3d    ; 61
   8:    de b7           in    r29, 0x3e    ; 62
   a:    80 e0           ldi    r24, 0x00    ; 0
   c:    90 e0           ldi    r25, 0x00    ; 0
   e:    9f 93           push    r25
  10:    8f 93           push    r24
  12:    00 d0           rcall    .+0          ; 0x14 <my_func+0x14>
  14:    9d 2f           mov    r25, r29
  16:    8c 2f           mov    r24, r28
  18:    01 96           adiw    r24, 0x01    ; 1
  1a:    9f 93           push    r25
  1c:    8f 93           push    r24
  1e:    80 e0           ldi    r24, 0x00    ; 0
  20:    90 e0           ldi    r25, 0x00    ; 0
  22:    9f 93           push    r25
  24:    8f 93           push    r24
  26:    00 d0           rcall    .+0          ; 0x28 <my_func+0x28>
  28:    89 81           ldd    r24, Y+1    ; 0x01
  2a:    9a 81           ldd    r25, Y+2    ; 0x02
  2c:    0f 90           pop    r0
  2e:    0f 90           pop    r0
  30:    0f 90           pop    r0
  32:    0f 90           pop    r0
  34:    0f 90           pop    r0
  36:    0f 90           pop    r0
  38:    86 39           cpi    r24, 0x96    ; 150
  3a:    91 05           cpc    r25, r1
  3c:    01 f0           breq    .+0          ; 0x3e <my_func+0x3e>
  3e:    84 3f           cpi    r24, 0xF4    ; 244
  40:    21 e0           ldi    r18, 0x01    ; 1
  42:    92 07           cpc    r25, r18
  44:    01 f0           breq    .+0          ; 0x46 <my_func+0x46>
  46:    84 36           cpi    r24, 0x64    ; 100
  48:    91 05           cpc    r25, r1
  4a:    01 f4           brne    .+0          ; 0x4c <my_func+0x4c>
  4c:    87 e6           ldi    r24, 0x67    ; 103
  4e:    90 e0           ldi    r25, 0x00    ; 0
  50:    00 c0           rjmp    .+0          ; 0x52 <my_func+0x52>
  52:    87 e9           ldi    r24, 0x97    ; 151
  54:    90 e0           ldi    r25, 0x00    ; 0
  56:    9a 83           std    Y+2, r25    ; 0x02
  58:    89 83           std    Y+1, r24    ; 0x01
  5a:    89 81           ldd    r24, Y+1    ; 0x01
  5c:    9a 81           ldd    r25, Y+2    ; 0x02
  5e:    0f 90           pop    r0
  60:    0f 90           pop    r0
  62:    df 91           pop    r29
  64:    cf 91           pop    r28
  66:    08 95           ret
  68:    86 ef           ldi    r24, 0xF6    ; 246
  6a:    91 e0           ldi    r25, 0x01    ; 1
  6c:    00 c0           rjmp    .+0          ; 0x6e <my_func+0x6e>
  6e:    01 97           sbiw    r24, 0x01    ; 1
  70:    00 c0           rjmp    .+0          ; 0x72 <__SREG__+0x33>

Kod:
00000000 <my_func>:
   0:    cf 93           push    r28
   2:    df 93           push    r29
   4:    00 d0           rcall    .+0          ; 0x6 <my_func+0x6>
   6:    cd b7           in    r28, 0x3d    ; 61
   8:    de b7           in    r29, 0x3e    ; 62
   a:    80 e0           ldi    r24, 0x00    ; 0
   c:    90 e0           ldi    r25, 0x00    ; 0
   e:    9f 93           push    r25
  10:    8f 93           push    r24
  12:    00 d0           rcall    .+0          ; 0x14 <my_func+0x14>
  14:    9d 2f           mov    r25, r29
  16:    8c 2f           mov    r24, r28
  18:    01 96           adiw    r24, 0x01    ; 1
  1a:    9f 93           push    r25
  1c:    8f 93           push    r24
  1e:    80 e0           ldi    r24, 0x00    ; 0
  20:    90 e0           ldi    r25, 0x00    ; 0
  22:    9f 93           push    r25
  24:    8f 93           push    r24
  26:    00 d0           rcall    .+0          ; 0x28 <my_func+0x28>
  28:    89 81           ldd    r24, Y+1    ; 0x01
  2a:    9a 81           ldd    r25, Y+2    ; 0x02
  2c:    0f 90           pop    r0
  2e:    0f 90           pop    r0
  30:    0f 90           pop    r0
  32:    0f 90           pop    r0
  34:    0f 90           pop    r0
  36:    0f 90           pop    r0
  38:    86 39           cpi    r24, 0x96    ; 150
  3a:    91 05           cpc    r25, r1
  3c:    01 f4           brne    .+0          ; 0x3e <my_func+0x3e>
  3e:    87 e9           ldi    r24, 0x97    ; 151
  40:    90 e0           ldi    r25, 0x00    ; 0
  42:    9a 83           std    Y+2, r25    ; 0x02
  44:    89 83           std    Y+1, r24    ; 0x01
  46:    89 81           ldd    r24, Y+1    ; 0x01
  48:    9a 81           ldd    r25, Y+2    ; 0x02
  4a:    0f 90           pop    r0
  4c:    0f 90           pop    r0
  4e:    df 91           pop    r29
  50:    cf 91           pop    r28
  52:    08 95           ret
  54:    84 3f           cpi    r24, 0xF4    ; 244
  56:    21 e0           ldi    r18, 0x01    ; 1
  58:    92 07           cpc    r25, r18
  5a:    01 f4           brne    .+0          ; 0x5c <my_func+0x5c>
  5c:    86 ef           ldi    r24, 0xF6    ; 246
  5e:    91 e0           ldi    r25, 0x01    ; 1
  60:    00 c0           rjmp    .+0          ; 0x62 <my_func+0x62>
  62:    84 36           cpi    r24, 0x64    ; 100
  64:    91 05           cpc    r25, r1
  66:    01 f4           brne    .+0          ; 0x68 <my_func+0x68>
  68:    87 e6           ldi    r24, 0x67    ; 103
  6a:    90 e0           ldi    r25, 0x00    ; 0
  6c:    00 c0           rjmp    .+0          ; 0x6e <my_func+0x6e>
  6e:    01 97           sbiw    r24, 0x01    ; 1
  70:    00 c0           rjmp    .+0          ; 0x72 <__SREG__+0x33>

Flag -Os iken bazı farklılıklar olduğunu görüyoruz yalnız farkların olduğu bölgelere bakarsak eğer, kodların yine aslında (neredeyse) tamamen aynı olduğunu söyleyebiliriz. Arduino UNO'daki ATmega328/P işlemcisinin AVR enhanced instruction setini kullandığını resmi datasheet'inde görebiliriz. Kodun farklı gözüken (Gözüken diyorum ama sadece karşılaştırma sıralamaları farklı. Yoksa branch'lerin ve jump'ların mantığı tamamen aynı) kısımlarındaki tüm instruction'ların da kaçar cpu clock yediğini yanlarına yazdım. Aşağıda görebilirsiniz.

Kod:
  3c:    01 f0           breq    .+0          ; 0x3e <my_func+0x3e> 1/2 cyc
  3e:    84 3f           cpi    r24, 0xF4    ; 244                   1 cyc
  40:    21 e0           ldi    r18, 0x01    ; 1 1 cyc               1 cyc
  42:    92 07           cpc    r25, r18                            1 cyc
  44:    01 f0           breq    .+0          ; 0x46 <my_func+0x46> 1/2 cyc
  46:    84 36           cpi    r24, 0x64    ; 100                   1 cyc
  48:    91 05           cpc    r25, r1                             1 cyc
  4a:    01 f4           brne    .+0          ; 0x4c <my_func+0x4c> 1/2 cyc
  4c:    87 e6           ldi    r24, 0x67    ; 103                   1 cyc
  4e:    90 e0           ldi    r25, 0x00    ; 0                     1 cyc
  50:    00 c0           rjmp    .+0          ; 0x52 <my_func+0x52>   2 cyc
  52:    87 e9           ldi    r24, 0x97    ; 151                   1 cyc
  54:    90 e0           ldi    r25, 0x00    ; 0                     1 cyc
  56:    9a 83           std    Y+2, r25    ; 0x02                     2 cyc
  58:    89 83           std    Y+1, r24    ; 0x01                     2 cyc
  5a:    89 81           ldd    r24, Y+1    ; 0x01                     2 cyc
  5c:    9a 81           ldd    r25, Y+2    ; 0x02                     2 cyc
  5e:    0f 90           pop    r0                                  2 cyc
  60:    0f 90           pop    r0                                  2 cyc
  62:    df 91           pop    r29                                 2 cyc
  64:    cf 91           pop    r28                                 2 cyc
  66:    08 95           ret                                     4/5 cyc
  68:    86 ef           ldi    r24, 0xF6    ; 246                   1 cyc
  6a:    91 e0           ldi    r25, 0x01    ; 1                     1 cyc

Kod:
3c:    01 f4           brne    .+0          ; 0x3e <my_func+0x3e> 1/2 cyc
  3e:    87 e9           ldi    r24, 0x97    ; 151                   1 cyc
  40:    90 e0           ldi    r25, 0x00    ; 0                     1 cyc
  42:    9a 83           std    Y+2, r25    ; 0x02                     2 cyc
  44:    89 83           std    Y+1, r24    ; 0x01                     2 cyc
  46:    89 81           ldd    r24, Y+1    ; 0x01                     2 cyc
  48:    9a 81           ldd    r25, Y+2    ; 0x02                     2 cyc
  4a:    0f 90           pop    r0                                  2 cyc
  4c:    0f 90           pop    r0                                  2 cyc
  4e:    df 91           pop    r29                                 2 cyc
  50:    cf 91           pop    r28                                 2 cyc
  52:    08 95           ret                                     4/5 cyc
  54:    84 3f           cpi    r24, 0xF4    ; 244                   1 cyc
  56:    21 e0           ldi    r18, 0x01    ; 1                     1 cyc   
  58:    92 07           cpc    r25, r18                            1 cyc
  5a:    01 f4           brne    .+0          ; 0x5c <my_func+0x5c> 1/2 cyc
  5c:    86 ef           ldi    r24, 0xF6    ; 246                   1 cyc
  5e:    91 e0           ldi    r25, 0x01    ; 1                     1 cyc
  60:    00 c0           rjmp    .+0          ; 0x62 <my_func+0x62>   2 cyc
  62:    84 36           cpi    r24, 0x64    ; 100                   1 cyc
  64:    91 05           cpc    r25, r1                             1 cyc
  66:    01 f4           brne    .+0          ; 0x68 <my_func+0x68> 1/2 cyc
  68:    87 e6           ldi    r24, 0x67    ; 103                   1 cyc
  6a:    90 e0           ldi    r25, 0x00    ; 0                     1 cyc

Compiler'lar ciddi ciddi tüm optimizason işlerini hallediyor. Açıkçası switch-case/if-else karşılaştırmasında karşımıza çıkan tüm genel durumlarda performanstan daha çok kod okunurluğunu ve anlaşılırlığını düşünmenin çok daha faydalı olacağına inanıyorum. Yine bir önceki mesajımda bahsettiğim üzere, performansın aşırı önemli olduğu durumlarda gerekli testler yapılarak karar vermek gerekir.

ATmega328/P datasheet: https://web.mit.edu/6.111/volume2/www/f2019/handouts/ATmega328P.pdf

AVR instruction set pdf'i: https://ww1.microchip.com/downloads/en/devicedoc/atmel-0856-avr-instruction-set-manual.pdf
 
Bu siteyi kullanmak için çerezler gereklidir. Siteyi kullanmaya devam etmek için çerezleri kabul etmelisiniz. Daha Fazlasını Öğren.…