Pagina 1 di 1

[C] switch-case vs if-else

Inviato: mar 3 feb 2009, 13:59
da Mario Vanoni
In inglese

http://www.safercode.com/blog/2008/10/2 ... speed.html

Ho sempre preferito switch-case ad if-else,
ma mai usato uno switch nello switch
come descritto nell'articolo, interessante.

Re: [C] switch-case vs if-else

Inviato: mar 3 feb 2009, 14:21
da aschenaz
Non ho capito lo scopo di quell'esempio:

Codice: Seleziona tutto

switch(a)
{
  case 1: /*do something*/
  case 2: /*do something*/
  case 3: /*do something*/
  default:
    switch(a)
    {
      case 4: /*do something*/
      case 5: /*do something*/
      case 6: /*do something*/
      default: /*do something*/
    }
}
Non sarebbe stato equivalente scrivere:

Codice: Seleziona tutto

switch(a)
{
  case 1: /*do something*/
  case 2: /*do something*/
  case 3: /*do something*/
  case 4: /*do something*/
  case 5: /*do something*/
  case 6: /*do something*/
  default: /*do something*/
}
:?:

Re: [C] switch-case vs if-else

Inviato: mar 3 feb 2009, 14:35
da nuitari
Personalmente li ho sempre usati interscambiabilmente in base alla semantica del codice. Diventa più una questione di lettura che altro.

Lo switch nidificato nell'esempio serve per sfruttare le caratteristiche dei compilatori C/C++ nella generazione del *codice macchina* allo scopo di ottimizzarlo per la velocità.
La logica è che indipendentemente da tutto il blocco default ha la priorità minore e che nel caso lo switch sia di piccole dimensioni viene usata una (performante) jump table. Per cui, suddividere un blocco switch isolando le occorrenze più probabili in uno switch di piccole dimensioni permette di forzare l'utlizzo di una jump table almeno per queste ultime.

Si tratta comunque di ottimizzazioni estreme, in cui la velocità è un obbiettivo mission critical (e richiedono una notevole conoscenza del comportamento del compilatore, con disassemblaggi al seguito).
Onestamente se si ha bisogno di performance così elevate, è quasi conveniente scrivere in assembler il codice relativo. Interessante comunque ^^

Re: [C] switch-case vs if-else

Inviato: mar 3 feb 2009, 14:58
da ZeD
Mario Vanoni ha scritto:In inglese

http://www.safercode.com/blog/2008/10/2 ... speed.html

Ho sempre preferito switch-case ad if-else,
ma mai usato uno switch nello switch
come descritto nell'articolo, interessante.
Mah, a me pare una mezza fesseria.. cioé
se capita d'avere, boh, + di 512 confronti allora la cosa magari inizia ad avere un senso (per i vari longjump)... tuttavia, qualcuno ha *effettivamente* visto che cambia? :)
prova1.c

Codice: Seleziona tutto

int main() {
    unsigned i = 0;
    switch (i) {
        case 1:
        case 2:
        case 3:
        default:
            switch (i) {
                case 4:
                case 5:
                case 6:
                default:
                    i += 10; /* operazione a caso */
            }
    }
}
prova2.c

Codice: Seleziona tutto

int main() {
    unsigned i = 0;
    switch (i) {
        case 1:
        case 2:
        case 3:
/*        default:
            switch (i) {*/
                case 4:
                case 5:
                case 6:
                default:
                    i += 10; /* operazione a caso */
            /*}*/
    }
}
diff prova{1,2}.c

Codice: Seleziona tutto

--- prova1.c    2009-02-04 09:23:22.000000000 +0100
+++ prova2.c    2009-02-04 09:23:52.000000000 +0100
@@ -4,13 +4,13 @@
         case 1:
         case 2:
         case 3:
-        default:
-            switch (i) {
+/*        default:
+            switch (i) {*/
                 case 4:
                 case 5:
                 case 6:
                 default:
                     i += 10; /* operazione a caso */
-            }
+            /*}*/
     }
 }
e vediamo l'assembly generato:

Codice: Seleziona tutto

$ for i in `seq 4`; do
    gcc -O$i -S prova1.c -o prova1_$i.s
    gcc -O$i -S prova2.c -o prova2_$i.s
    diff prova1_$i.s prova2_$i.s
done

--- prova1_1.s  2009-02-03 14:56:48.000000000 +0100
+++ prova2_1.s  2009-02-03 14:56:48.000000000 +0100
@@ -1,4 +1,4 @@
-       .file   "prova1.c"
+       .file   "prova2.c"
        .text
 .globl main
        .type   main, @function
--- prova1_2.s  2009-02-03 14:56:48.000000000 +0100
+++ prova2_2.s  2009-02-03 14:56:48.000000000 +0100
@@ -1,4 +1,4 @@
-       .file   "prova1.c"
+       .file   "prova2.c"
        .text
        .p2align 4,,15
 .globl main
--- prova1_3.s  2009-02-03 14:56:48.000000000 +0100
+++ prova2_3.s  2009-02-03 14:56:48.000000000 +0100
@@ -1,4 +1,4 @@
-       .file   "prova1.c"
+       .file   "prova2.c"
        .text
        .p2align 4,,15
 .globl main
--- prova1_4.s  2009-02-03 14:56:49.000000000 +0100
+++ prova2_4.s  2009-02-03 14:56:49.000000000 +0100
@@ -1,4 +1,4 @@
-       .file   "prova1.c"
+       .file   "prova2.c"
        .text
        .p2align 4,,15
 .globl main
$
in pratica non ci sono differenze :)

Re: [C] switch-case vs if-else

Inviato: mar 3 feb 2009, 15:10
da conraid
ZeD ha scritto: prova1.c

Codice: Seleziona tutto

int main() {
    unsigned i = 0;
    switch (i) {
        case 1:
        case 2:
        case 3:
        default:
            switch (i) {
                case 4:
                case 5:
                case 6:
                default:
                    i += 10; /* operazione a caso */
            }
    }
}
prova2.c

Codice: Seleziona tutto

int main() {
    unsigned i = 0;
    switch (i) {
        case 1:
        case 2:
        case 3:
        default:
            switch (i) {
                case 4:
                case 5:
                case 6:
                default:
                    i += 10; /* operazione a caso */
            }
    }
}
in pratica non ci sono differenze :)
Perché avrebbero dovuto esserci se non ci sono nemmeno nel codice sorgente?

Re: [C] switch-case vs if-else

Inviato: mar 3 feb 2009, 15:29
da Vito
Non sono due strutture perfettamente equivalenti?


Non si aumenta la complessità dell'algoritmo inoltre nidificando dei case?

EDIT: Per quanto riguarda la scelta di if-else / sitch-case a seconda di quale algoritmo devo scrivere utilizzo una delle due strutture.
La nidificazione di if-else è indispensabile quando bisogna fare dei confronti particolari (esempio prelevare da una matrice gli elementi tra le due diagonali principali).
Uno switch-case invece è utilissimo quando si devono lavorare sulla variazione del valore di una variabile..anche perchè è molto più sintetico ed espressivo come costrutto!

Re: [C] switch-case vs if-else

Inviato: mar 3 feb 2009, 20:07
da Mario Vanoni
nuitari ha scritto:Personalmente li ho sempre usati interscambiabilmente in base alla semantica del codice. Diventa più una questione di lettura che altro.

Lo switch nidificato nell'esempio serve per sfruttare le caratteristiche dei compilatori C/C++ nella generazione del *codice macchina* allo scopo di ottimizzarlo per la velocità.
La logica è che indipendentemente da tutto il blocco default ha la priorità minore e che nel caso lo switch sia di piccole dimensioni viene usata una (performante) jump table. Per cui, suddividere un blocco switch isolando le occorrenze più probabili in uno switch di piccole dimensioni permette di forzare l'utlizzo di una jump table almeno per queste ultime.

Si tratta comunque di ottimizzazioni estreme, in cui la velocità è un obbiettivo mission critical (e richiedono una notevole conoscenza del comportamento del compilatore, con disassemblaggi al seguito).
Onestamente se si ha bisogno di performance così elevate, è quasi conveniente scrivere in assembler il codice relativo. Interessante comunque ^^
Hai ragione, e` la forzatura della jump-table.

Ma sarebbe interessante,
su una macchina Intel Core 2 o i7,
vedere le differenze tra gcc e icc.

Re: [C] switch-case vs if-else

Inviato: mer 4 feb 2009, 9:24
da ZeD
conraid ha scritto:Perché avrebbero dovuto esserci se non ci sono nemmeno nel codice sorgente?
Perché non so fare copia-incolla -.-
I 2 file sono effettivamente diversi: nel primo ci sono 2 switch annidati (0-3 + 4-6), nel secondo è uno unico (0-6)