switch-case vs. if-else?



  • afdasfd schrieb:

    Erinnerungen mögen trügen. Im Grunde sollte es egal sein. Der Compiler dürfte das zum gleichen Code verhackstücken.

    Das tut er nicht, wie man mit einem Disassembler leicht feststellen kann. Der resultierende Code ist _sehr_ unterschiedlich.



  • SeppJ schrieb:

    Wenn du viele Bedingungen fest im Code stehen hast, machst du wahrscheinlich etwas falsch.

    Aha. Du bist über das Stadium von Taschenrechnerprogrammen also nie hinaus gekommen?

    Jede windige State-Machine macht Gebrauch von mehr oder weniger vielen, festen Bedingungen.


  • Mod

    Hilf dir doch selber.



  • SeppJ schrieb:

    Hilf dir doch selber.

    Sorry, aber fällt dir eigentlich auf wie nutzlos deine erste "Antwort" war? Das Schlimme ist nur, das Anfänger auf so einen Stuß reinfallen könnten und tatsächlich dem Quatsch folgen, den du hier von dir gibst.



  • Erinnerungen mögen trügen. Im Grunde sollte es egal sein. Der Compiler dürfte das zum gleichen Code verhackstücken

    kommt auf den Kompiler an

    int if_test(int a)
    {
      if(a == 1){ return 10; }
      else if(a == 2){ return 20; }
      else if(a == 3){ return 30; }
      return 0;
    }
    
    int switch_test(int a)
    {
      switch(a)
      {
        case 1: return 10;
        case 2: return 20;
        case 3: return 30;
      }
      return 0;
    }
    

    http://gcc.godbolt.org/

    gcc 6.2 -O2

    if_test(int):
            cmp     edi, 1
            mov     eax, 10
            je      .L1
            cmp     edi, 2
            mov     eax, 20
            je      .L1
            cmp     edi, 3
            mov     edx, 0
            mov     eax, 30
            cmovne  eax, edx
    .L1:
            rep ret
    switch_test(int):
            sub     edi, 1
            xor     eax, eax
            cmp     edi, 2
            ja      .L9
            mov     eax, DWORD PTR CSWTCH.2[0+rdi*4]
    .L9:
            rep ret
    CSWTCH.2:
            .long   10
            .long   20
            .long   30
    

    clang 3.9 -O2

    if_test(int):                            # @if_test(int)
            dec     edi
            cmp     edi, 2
            ja      .LBB0_2
            lea     eax, [rdi + 4*rdi]
            lea     eax, [rax + rax + 10]
            ret
    .LBB0_2:
            xor     eax, eax
            ret
    
    switch_test(int):                       # @switch_test(int)
            dec     edi
            cmp     edi, 2
            ja      .LBB1_2
            lea     eax, [rdi + 4*rdi]
            lea     eax, [rax + rax + 10]
            ret
    .LBB1_2:
            xor     eax, eax
            ret
    

    Wenn du viele Bedingungen fest im Code stehen hast, machst du wahrscheinlich etwas falsch. Außerhalb von Beispielcodes habe ich jedenfalls noch nie switch benutzt.

    bei Statemachines braucht man switch damit es übersichtlich bleibt - oder siehst du das anders?


  • Mod

    Gast3 schrieb:

    bei Statemachines braucht man switch damit es übersichtlich bleibt - oder siehst du das anders?

    Ich habe bereits etwas dazu gesagt, möchte aber nicht weiter ins Detail gehen, weil ich dem Threadersteller in keiner Weise, auch nicht indirekt, helfen möchte.



  • Tomot schrieb:

    Jede windige State-Machine macht Gebrauch von mehr oder weniger vielen, festen Bedingungen.

    Ja, aber wenn man über das Stadium von Taschenrechnerprogrammen hinaus ist, nimmt man dafür passende Datenstrukturen, statt if-Kaskaden wie in der 3. Klasse zu schreiben.



  • @Tomot:
    Ich ziehe weder switch noch if-then-else vor. Warum auch? Wenn es wirklich um Geschwindigkeit geht, schaue ich ob ich die Komplexität O(n) des Programms herunterschrauben kann und profile das Programm. VerySleepy ist da hilfreich.

    Die Frage ist dann interresant wenn man richtige üble Zeitbeschränkungen hat. Wenn man innerhalb von 10 Mikrosekunden X Datensätze verarbeiten muss.

    Ich habe auch schon in einem 1ms Interrupt switch ohne Reue switch benutzt.

    The real problem is that programmers have spent far too much time worrying about efficiency in the wrong places and at the wrong times; premature optimization is the root of all evil (or at least most of it) in programming.

    Knuth Donald
    Quelle: https://en.m.wikiquote.org/wiki/Donald_Knuth

    @SeppJ:
    Alles in Ordnung? Du klingst irgentwie gereizt.

    Switch Anweisungen brauche ich sehr viele. Ich nutze viel die WinAPI. Und die Eventfunktion ist voll von switch Anweisungen.

    //...
    switch (MessageID)
    case WM_COMMAND:
    switch FirstMsgParam:
    case IDC_BUTTON_OK:
    break;
    case IDC_BUTTON_SAVE;
    break;
    //...
    

    Ich muss auch öfters ein Zustandsdiagramm implementieren. So ein Protokoll ist halt zustandsbasiert. Dann modelliere ich erst das Diagramm, und implementiere exakt dieses in einer while(true) switch(State) Anweisung s.d. der Zustand 1 im Statechart auch im Code mit State=1 gekennzeichnet ist.

    Und mal nebenbei. Im C++ Unterforum will einer eine eigene itoa implementieren. Und da bietet sich halt ein Zustandsdiagramm an. Es gibt halt Leute wie ich, die öfters nur sehr kleine Mikrochips mit wenigen kByte Flash zur Verfügung haben.



  • So wirklich oft braucht man das in der Tat nicht. Auch Zustandsautomaten kann man anders implementieren.
    Aber wenn, dann würde ich ab ein paar Abfragen switch-case benutzen, weil man das einfacher debuggen kann. Habe schon paar mal fremden Code durchdebuggt, wo in einer Schleife erst 50 ifs übersprungen werden, bevor man an die richtige Stelle kommt. Das macht keinen Spass.



  • Ich hab vor langer Zeit eine Turmite programmiert (googelt danach); hat mit einem Zustandsautomaten hervorragend funktioniert (und das war ein 7Mhz prozessor).
    Those were the days my friend...



  • Mechanics schrieb:

    Habe schon paar mal fremden Code durchdebuggt, wo in einer Schleife erst 50 ifs übersprungen werden, bevor man an die richtige Stelle kommt. Das macht keinen Spass.

    ...und kostet im realen Code Rechenzeit - deswegen wurden ja auch switch-case erfunden.

    Nur um das mal aufzuklären: es geht mir hier um Embedded Code, bei dem ich gerade auf der Jagd nach Einsparungen im Nanosekundenbereich bin. Und da ist eben die Frage, ob sich bei einer Abfolge if-else-if schon ein switch-case lohnt (einen vernünftigen Profiler gibt es für die Plattform leider nicht, sonst hätte ich das schon lange gemessen).

    50 kaskadierte if-else wie im Beispiel oben sind hingegen eindeutig, das ist lausiger Programmierstil (und wird wahrscheinlich von Programmierern gemacht, die der Meinung sind, switch-case sind nur für akademische Betrachtungen geeignet und werden im realen Code nie gebraucht).


  • Mod

    Tomot schrieb:

    50 kaskadierte if-else wie im Beispiel oben sind hingegen eindeutig, das ist lausiger Programmierstil (und wird wahrscheinlich von Programmierern gemacht, die der Meinung sind, switch-case sind nur für akademische Betrachtungen geeignet und werden im realen Code nie gebraucht).

    Das ist ja nicht zum Aushalten! Du kapierst nicht einmal, was andere gesagt haben, aber machst dich darüber lustig. Wenn man in einem Programm an einer Stelle 50 Verzweigungen hat, ist das Problem ist nicht, dass man diese nicht als switch schreiben sollte, sondern das Problem ist dann, dass man in deinem Programm 50 Verzweigungen an einer Stelle hat! Aber das kapiert wohl jemand nicht, der anscheinend wirklich seine Zustandsänderungen hart im Code codiert hat und auch noch stolz darauf ist, wie professionell das doch ist, solch ein komplexes Programm geschrieben zu haben 🙄



  • Tomot schrieb:

    Hi,

    ab wie vielen Bedingungen ist denn ein switch-case einem

    if (bedingung)
    {
    }
    else if (bedingung)
    {
    }
    else ...
    

    vorzuziehen?

    So weit ich mich erinnere war switch-case auf Grund irgend welcher CPU-Jumptables irgendwann effektiver!?

    Danke!

    Sobald größer/kleiner Vergleiche hast, musst du if(-else) nehmen.

    Musst du nur schauen ob dein Wert einem bestimmten anderen Wert aus einer überschaubaren Menge entspricht nimmst du switch.

    Vergleichst du aber nur mit einem Wert, dann kannst du auch wieder if(-else) nehmen.

    Beachte hierbei, mit switch kann man elegante Sachen machen.
    Man kann z.b. eine Abfolge von Ausführungen durchrutschen lassen.

    Man beachte, es ist kein break gesetzt, d.h. sobald eine Bedingung erfüllt ist, sind auch alle Folgebedingungen erfüllt, bzw. wird die Anweisung daraus ausgegeben:

    switch(bla) {
    case A: ;
    case B: ;
    case C: ;
    default: ;
    }
    

    ein verständliches Beispiel:
    Frage: Welche Wochentage folgen auf den XY?

    // Pseudocode
    switch(XY){
    case MO: print MONTAG;
    case DI: print Dienstag;
    case MI: print Mittwoch;
    case DO: print Donnerstag;
    case FR: print Freitag;
    case SA: print Samstag;
    default: print Sonntag;
    ]
    

    Wäre also XY ein Freitag, dann wird auch der Samstag und Sonntag ausgegeben.

    Möchtest du das mit if umsetzen, dann wird das nicht so schön.



  • Und ja, wenn switch möglich und praktikabel ist, dann sollte man es auch nehmen, denn das kann der Compiler besser optimieren.



  • Praktiker schrieb:

    Vergleichst du aber nur mit einem Wert, dann kannst du auch wieder if(-else) nehmen.

    Damit meine ich, wenn man einen Wert mit einem ganz bestimmten Wert vergleicht.

    Z.b. ob bla == TRUE ist.



  • sondern das Problem ist dann, dass man in deinem Programm 50 Verzweigungen an einer Stelle hat! Aber das kapiert wohl jemand nicht, der anscheinend wirklich seine Zustandsänderungen hart im Code codiert hat und auch noch stolz darauf ist

    wenn das keine "richtige" Statemachine ist sondern einfach nur viele if-Statements auf einem Haufen könnte ich dir recht geben - aber was ist wenn seine Statemachine wirklich sehr komplex ist - oder mehrere Transitionmatrizen von Hand zusammengefasst sind? Ist ja auch nicht so das wir alle hier immer den gleichen Projekterfahrungshorizont haben

    btw ist es aber für die Performanzfrage auch unrelevant ob es handgeschriebener oder generierter Code ist - und selten(oder nie) switch zu verwenden ist auch irgendwie seltsam/ungewöhnlich



  • SeppJ schrieb:

    Wenn du viele Bedingungen fest im Code stehen hast, machst du wahrscheinlich etwas falsch. Außerhalb von Beispielcodes habe ich jedenfalls noch nie switch benutzt. Insofern ist es wahrscheinlich müßig, sich darüber große Gedanken zu machen, bevor man nicht wirklich mal auf einen praktischen Fall stößt.

    Für welcher Wochentag ist heute und mach dann etwas entsprechendes ist Switch immer gut zu gebrauchen.
    Wichtig ist nur, dass das, was du ausgeben möchtest, nicht fest im Code ist.

    Zu gebrauchen z.b. für einen Terminplaner.



  • Hab noch etwas vergessen:

    Praktiker schrieb:

    Musst du nur schauen ob dein Wert einem bestimmten anderen Wert aus einer überschaubaren Menge entspricht nimmst du switch.

    Ist die Menge, mit der verglichen werden soll, nicht mehr überschaubar, dann ist weder if/else noch switch das Problem, sondern die Datenstruktur.

    Bsp:
    Wenn du wissen willst, ob ein bestimmtes Wort in einem Wörterbuch vorhanden ist, dann packst du ganz sicher nicht das ganze Wörterbuch in eine Switchanweisung.
    Und eine Kaskade von if Anweisungen machst du da auch nicht.


  • Mod

    Praktiker schrieb:

    Für welcher Wochentag ist heute und mach dann etwas entsprechendes ist Switch immer gut zu gebrauchen.
    Wichtig ist nur, dass das, was du ausgeben möchtest, nicht fest im Code ist.

    Zu gebrauchen z.b. für einen Terminplaner.

    Was möchtest du bei einem Terminplaner switchen? Ein Terminplaner ist doch ein Paradebeispiel für eine Anwendung, bei der möglichst viel dynamisch gehalten werden sollte.



  • Was möchtest du bei einem Terminplaner switchen? Ein Terminplaner ist doch ein Paradebeispiel für eine Anwendung, bei der möglichst viel dynamisch gehalten werden sollte.

    es ist doch völlig unrelevant ob die Software sehr dynamisch ist oder nicht - wenn es irgendwo viele If-Statements (z.B. in einer von mehreren fixen Statemachine gibt - die es vielleicht nicht so oft in einem Terminplaner gibt) wo nur ein State verglichen werden sollte man dafür sinnvollerweise switch verwenden


Anmelden zum Antworten