goto's verwenden



  • Blue-Tiger schrieb:

    Ich verwende nie nie nie nie welche.

    for(int i=0; i<10; i++)
      for(int u=0; u<10; u++)
        if(array[i][u] == blabla) goto weiter;
    //element nbicht gefunden
    weiter:
    //element gefunden
    

    ein kleines und einfaches beispiel. wie realisiert man disen code ohne goto?

    Blue-Tiger schrieb:

    "Only really bad and really good programmers use goto"

    einen eigenen compiler bzw. assembler kein compiler schreibe ich auch gerade... :p aber ich würde mich nicht als ein überdurchschnittlichen programmierer einschätzen.



  • pi88el schrieb:

    Blue-Tiger schrieb:

    Ich verwende nie nie nie nie welche.

    for(int i=0; i<10; i++)
      for(int u=0; u<10; u++)
        if(array[i][u] == blabla) goto weiter;
    //element nbicht gefunden
    weiter:
    //element gefunden
    

    ein kleines und einfaches beispiel. wie realisiert man disen code ohne goto?

    So:

    inline bool contains(array, blabla)
    {
      for(int i=0; i<10; i++)
        for(int u=0; u<10; u++)
          if(array[i][u] == blabla) return true;
      return false;
    }
    


  • Christoph schrieb:

    inline bool contains(array, blabla)
    {
      for(int i=0; i<10; i++)
        for(int u=0; u<10; u++)
          if(array[i][u] == blabla) return true;
      return false;
    }
    

    😮
    ich habe mir schon gedacht das jemand diese art bringen wird. 🙂
    jetzt muss man halt abwegen wann was mehr sinn macht. bei sehr vielen verschachtelten schleifen, die immer auf verschiedene array, mit verschidenen diminsionen und größen, nach verschiedenen ausdrücken zu suchen, ist entweder eine sehr variable gehaltene funktion nötig, die aber den ablauf ausbremst oder mehrere solcher funktionen nötig die (in meinen augen) den code zumüllen. da ist doch dan ein kleines goto übersichtlicher als nach einer funktion zu suchen, die vielleicht ganz wo anders liegt, und die dann auch noch zu verstehen wenn sie so allgemein gehalten wird dass sie für einige verschiedene abfrage konzipiert ist.
    außerdem ist die inline funktion soweit ich weis etwas begrentzt der compieler fügt nicht immer den code ein, sondern rufft manchmal die funktion ganz normal auf.



  • Man unterteilt sowieso eine Methode in mehere Submethoden, das ist immer übersichtlicher.

    sehr "übersichtlicher" Code:

    c:
    for x
    {
        for y 
        {
            if blaaa goto a;
        }
    }
    
    a:
    for x
    {
        for y 
        {
            for y 
            {
                if foo goto c; else goto b;
            }
    }
    b:
    
    bool xxx = true;
    do
    {
        if ( blaaa() ) xxx = foo();
    } while ( xxx == true );
    

    Es ist nun einmal so, dass in 99,9% der Fälle es etwas besseres gibt daher ist mein Gebrauch auch sehr eingeschränkt.

    👍
    Unterteile deine Methode in Submethoden dann hast du bereits 99,9% der gotos eleminiert.



  • for(int i=0; i<10; i++)
      for(int u=0; u<10; u++)
        if(array[i][u] == blabla) break;
      if(array[i][u] == blabla) break;
    
    bool run = 1;
    for(int i=0; i<10 && run; i++)
      for(int u=0; u<10; u++)
        if(array[i][u] == blabla) { run = 0; break; }
    
    for(int i=0; (i<10) && (array[i][u] != blabla); i++)
      for(int u=0; (u<10) && (array[i][u] != blabla); u++)
    


  • Blue-Tiger schrieb:

    wie sieht es bei euch aus?? verwendet ihr auch welche, oder versucht ihr es irgendwie zu umgehen?

    Ich verwende nie nie nie nie welche. "Only really bad and really good programmers use goto". Und mit "Really good" sind nur die absoluten Ober-Gurus gemeint, die ihre eigenen Compiler schreiben und seit 20 Jahren programmieren, und davon bin ich meilenweit und 12 Jahre entfernt.

    Verstehe ich nicht. Weshalb wird das goto bei Profis denn verzeihbar? Oder ist es bloß die Unantastbarkeit der Gurus, d.h. wenn ein Profi es benutzt MUSS es gut sein? Ein goto ist auch bei Nicht-Gurus allemal besser als wie ein Irrer Hilfszustände einzuführen, eine kleine Funktion in Stücke zu reißen (auch wenn es u.U. nicht logisch ist) oder Exceptions zu mißbrauchen. Anfänger sollten die Finger davon lassen, diese Meinung teile ich.

    Ich kann mich aber nur an eine Situation erinnern in der ich ein goto benutzt habe und das ist nachher auch wieder rausgeflogen.



  • gotos sind manchmal schon sinnvoll.
    Deswegen das Programm in irgendwelche eh nur einmal aufgerufene Methoden zu unterteilen oder fünf mal irgendeine Variable abzufragen, nur um aus Prinzip kein goto zu machen finde ich sinnfrei, ein goto ist da meist wesentlich einfacher zu überblicken.

    Besonders bei verschachtelten Schleifen mit einer Sprungmarke direkt dadrunter ist ein goto sehr leicht zu lesen, alles andere entweder länger und/oder schwerer zu lesen.
    Da gibt es nix schlimmes dran, fies wirds nur wenn das goto durchs halbe Programm springt oder man mal zum einen mal zum anderen springt und nicht ganz genau ersichtlich ist wann etc.



  • DEvent schrieb:

    Unterteile deine Methode in Submethoden dann hast du bereits 99,9% der gotos eleminiert.

    ...und dein programm verbrät 99,9% seiner rechenzeit mit dem code für funktionsaufrufe 😉



  • net schrieb:

    ...und dein programm verbrät 99,9% seiner rechenzeit mit dem code für funktionsaufrufe 😉

    Sehr unwahrscheinlich.

    Was hat ein Funktionsaufruf denn - gerade wenn man es zum "Zusammenfalten" von Codefragmenten benutzt - groß an Frame? Stack kurz schieben, evtl. Rückgabewert in Register legen. Abgesehen davon optimiert der Compiler das zum Teil inline, wenn die Funktion nur einmal aufgerufen wird, d.h. er macht intern das, was man lang ausprogrammiert hätte.

    Und kein Funktionsaufruf braucht soviel Rechenzeit wie ein Algorithmus, in dem irgendwas passiert. Irgendwas suchen, sortieren, anordnen, da geht die CPU-Zeit hin. Alles andere ist Propaganda, das wirst Du mit jedem Profiler rasch erkennen. Wieviele CPU-Zyklen dauert der Aufbau eines Dialogfensters? Wieviele Zyklen ein Funktionsaufruf?

    Abgesehen davon nützt ein schnelles Programm, das nicht funktioniert, da man es nicht überblickt und Fehler nicht findet, nichts. Man sollte zunächst immer erst die Funktion sicherstellen, dann Tunen. Dann weiß man nämlich auch, wo die Zeit steckt.



  • @marcus:
    man sieht öfters mal funktionen mit nur einer zeile z.b. in c++ sind ja sehr beliebt diese 'get/set funktionen'. wenn das 'geinlined' wird isses gut. wenn nicht, dann hat so'ne funktion kaum was zu tun und ist grösstenteils mit sich selbst beschäftigt.



  • In C ist goto manchmal ok.
    In C++ ist nie ok.



  • wisser schrieb:

    In C ist goto manchmal ok.
    In C++ ist nie ok.

    Wenn umsichtig und begründet eingesetzt, ist goto auch in C++ in Ordnung.

    net schrieb:

    @marcus:
    man sieht öfters mal funktionen mit nur einer zeile z.b. in c++ sind ja sehr beliebt diese 'get/set funktionen'. wenn das 'geinlined' wird isses gut. wenn nicht, dann hat so'ne funktion kaum was zu tun und ist grösstenteils mit sich selbst beschäftigt.

    Man kann sich in der Frage imo durchaus auf die aktuellen C++ Compiler verlassen, ohne in Panik zu verfallen, weil die Funktionsaufrufe vllt. die Performance ruinieren 😉



  • Wenn man schon so weit ist, das man Funktionsaufrufe wegoptimieren will, dann sollte man vielleicht eh Assembler nehmen.

    gotos vermeidet man, wie bereits gesagt wurde, dadurch das man Funktionen benutzt. Man schreibt viele kleine Funktionen. Wenn man auf Funktionen stößt, die mehrere hundert Zeilen haben, dann hat man sicher etwas unschönes gemacht.

    Außerdem ist

    if(contains(table, value))
      // do sth.
    

    bei weitem leserlicher, als ein

    for(int i=0; i<10; i++)
      for(int u=0; u<10; u++)
        if(array[i][u] == blabla) goto gefunden;
    goto nicht_gefunden;
    gefunden:
    //do sth.
    nicht_gefunden:
    

    viel leserlicher und leichter zu verstehen.

    @pi88el
    lass mich raten, du schreibst vermutlich eh kleinere Hobby-Projekte, an denen du alleine arbeitest. Dann wirst du auch nicht so schnell auf die Probleme stoßen, die goto bringt.



  • net schrieb:

    @marcus:
    man sieht öfters mal funktionen mit nur einer zeile z.b. in c++ sind ja sehr beliebt diese 'get/set funktionen'. wenn das 'geinlined' wird isses gut. wenn nicht, dann hat so'ne funktion kaum was zu tun und ist grösstenteils mit sich selbst beschäftigt.

    Selbst wenn eine solche Funktion nicht inline expandiert wird, ist sie selten ein Problem, da es ja nicht nur auf die Ausführngszeit einer Funktion sondern ganz extrem auch auf die Häufigkeit des Aufrufs ankommt (Stichwort: 80/20-Regel, die man besser als 90/10-Regel im Kopf behält).
    Es ist und bleibt nun mal so, dass sich (Low-Level-)Performance am Besten mit einem Profiler und realisitischen Eingabedaten tunen lässt und der Weg von Funktion -> keine Funktion ist immer leichter als andersherum.

    Blue-Tiger schrieb:

    Es ist nicht nur eine Frage des Ueberblicks sondern auch eine Frage des guten Geschmacks, guten Stils, guten Benehmens, ...
    Abgesehen davon, dass das Debuggen mit Debugger dich in die Klappsmuehle bringen wuerde, wuerdest du mit Goto's z. B. das Stack-Unwinding bei C++ - Klassen verhindern, und kannst damit sehr leicht ohne es ueberhaupt zu merken Speicherlecks produzieren.

    Wie geht das? C++ gotos sind keine longjumps und somit auf eine Funktion beschränkt. Gleichzeitig darfst du auch nicht über Initialisierungen hinweg springen. Was passieren kann ist sowas:

    int func(int x) {
      int* i = new int(22);
      if (x == 0) {
        goto end;
      }
      // ...
      delete i;
    end:
      return 42;
    }
    

    Aber das ist kein Problem von goto sondern mangelende Anwendung des RAII-Idioms.



  • HumeSikkins schrieb:

    und der Weg von Funktion -> keine Funktion ist immer leichter als andersherum.

    ich glaub' das ist beides gleich schwer/leicht...



  • net schrieb:

    HumeSikkins schrieb:

    und der Weg von Funktion -> keine Funktion ist immer leichter als andersherum.

    ich glaub' das ist beides gleich schwer/leicht...

    Nein, da du ansonsten mehr Code schreiben musst und diesen an mehreren Stellen warten musst. Daher ist die Vorgehensweise besser, das man erst alles in Funktionen packt und sollte man dann wirklich in den äußerst seltenen Fall kommen, das einem selbst ein Funktionsaufruf zu viel ist, dann kann man es eben ändern.



  • rüdiger schrieb:

    Nein, da du ansonsten mehr Code schreiben musst und diesen an mehreren Stellen warten musst. Daher ist die Vorgehensweise besser, das man erst alles in Funktionen packt...

    naja, es gibt sghon ein paar tricks, um den gleichen code an verschiedenen stellen zu benutzen, ohne funktionsaufrufe zu haben (etwa makros, templates, #include "code.c" wo man's braucht)...

    aber eigentlich meinte ich das umwandeln von code 'mit funktion' <---> 'ohne funktionen' (wenn man das manuell macht). dürfte beides etwa gleich fummelig sein.



  • @net
    Es ging mir um die Ergebnisse des Profilers. Die lassen sich umso leichter interpretieren, je modularer der Code ist. Die Entscheidung, ob es sich lohnt eine Funktion zu inlinen lässt sich mit einem Profiler spielend herausfinden. Bei dem umgekehrten Fall, nämlich ist es sinnvoller Code in eine Funktion auszulagern, ist ein Profiler hingegen keine große Hilfe.
    Man sollte nicht vergessen, dass inline-Code immer höhere physische Abhängigkeiten hat. Egal ob inline-Funktion, Makro, include. Eine Änderungen an der Implementation und du musst *alle* Aufrufer mindestens neu bauen.



  • net schrieb:

    naja, es gibt sghon ein paar tricks, um den gleichen code an verschiedenen stellen zu benutzen, ohne funktionsaufrufe zu haben (etwa makros, templates, #include "code.c" wo man's braucht)...

    Die Anwendung würde ich gerne sehen, wo man #include "code.c" braucht und keine Funktion verwenden kann...

    [Ein alter C-Compiler für einen 8Bit-Microcontroller zählt in diesem Fall nicht als Beispiel.]



  • rüdiger schrieb:

    gotos vermeidet man, wie bereits gesagt wurde, dadurch das man Funktionen benutzt. Man schreibt viele kleine Funktionen.

    Tendiert manchmal zu ekligem Code, besonders wenn man Hilfsstrukturen einführen muß um verschiedene Endzustände der Schleife zurückzugeben.


Anmelden zum Antworten