Eine Frage am Rande ("Goto"?)



  • Hallo,
    ich wollte nur mal fragen, was es mit dem Befehl "Goto" auf sich hat. Ich lese gerade ein Buch über C++ und in dem steht, dass man es auf jeden Fall vermeiden sollte diesen Befehl zu benutzen. Es scheint mir aber doch ganz sinnvoll, wenn man zu verschiedenen abschnitten im code springen kann. Was ist also so schlecht an diesem Befehl? Giebt es da eventuell einen Haken oder bug oder sowas??
    Danke!



  • Es gibt halt fast immer bessere Möglichkeiten. Die Zahl der Fälle, wo die beste Lösung ein goto ist, ist so gering, dass man dieses Schlüsselwort ohne Probleme aus der Sprache entfernen könnte und nix würde abgehen. Anfängern gibt man deshalb natürlich gerne den Tipp, es einfach nicht zu benutzen.



  • Mit dem befehl goto machst du dein ganzes script total unübersichtlich, da du mit ihm an jede beliebige Stelle im Code springen kannst!



  • Uhahaha jetzt muss ich natürlich auch meinen Senf dazugeben(*zwinker*)

    Imho erlauben Campiler manche Dinge nicht, bzw springen nicht exakt zum Label(Weil es u.U. nicht geht)

    goto label;
    int x;
    
    label:
    if(x == 3)
     tuwas();
    x = 3;
    
    tuwasanderes();
    

    Wird zu tuwasanderes(); springen, wobei das ein schlechtes Beispiel ist, weil man eigentlich das dazwischen wegoptimieren könnte 😃

    Das ist ein weiterer Beweis für Fred123's Antwort.

    Sei noch zuletzt gesagt:
    Anfänger benutzen ogt goto(es sei den sie kennen's nich 😃 )
    Fortgeschrittene benutzen es nie
    Erfahrene benutzen es manchmal

    Ich sag nich ob das stimmt oder nich, sonst gib's ne Diskusion!



  • Jeder Programmierer, der etwas auf sich hält, benutzt die Befehle 'break', 'continue' und vor allem 'goto' nicht, aus Lesbarkeits- und Performacegründen. Sie lassen sich allesamt durch Verwendung von Schleifen, if-Anweisungen usw. vermeiden.



  • aus [...] Performacegründen

    Stimmt. Wenn ich mir mein Assembler Listing im Compiler anschaue... das ist schon verdammt komplex mit so einem goto aus einer Schleife zu springen. Brauch das viele Befehle... und die Laufzeit erst...

    Und wie du break nicht verwenden willst und dann auch noch lesbaren und schnellen Code schreiben willst ist mir ein Rätsel...

    Du machst dann eher so

    bool ok = true;
    for(int i = 0;i < 100 && ok; ++i){
      ...
      if(fehler())     //Hoffen dass wir noch zum Schleifenende kommen
        ok = false;
    }
    

    gell?

    Ich finde auch immer das break überhauptnicht für sich spricht. break, break... brechen! Ne... da wird doch gar nix gebrochen!



  • das problem mit goto ist, dass sich der programmfluss teilweise nicht mehr direkt aus dem quellcode erschliesst. es kann teilweise sehr unübersichtlich werden, wenn an dutzende verschiedene stellen gesprungen wird, mal nach "oben", mal nach "unten" usw.

    break und continue hingegen sorgen nur dafür, dass ein codeblock übersprungen oder abgebrochen wird. egal was in einem block mit break oder continue passiert, es wird auf jeden fall der nachfolgende block als nächstes abgearbeitet.

    break und continue sorgen sogar häufig dafür, dass code übersichtlicher wird.



  • Hi,

    Praetorian schrieb:

    Jeder Programmierer, der etwas auf sich hält, benutzt die Befehle 'break', 'continue' und vor allem 'goto' nicht, aus Lesbarkeits- und Performacegründen. Sie lassen sich allesamt durch Verwendung von Schleifen, if-Anweisungen usw. vermeiden.

    ich finde Pauschalisierungen pauschal schlecht. Denn in der Kernel- bzw. Treiberprogrammierung z.B. wird goto ständig verwendet, und zwar gerade wegen der Übersichtlichkeit. Deiner Aussage nach würde ja kein Kernelprogrammierer etwas auf sich halten... 😉

    http://ezs.kr.hsnr.de/TreiberBuch/html/sec.technik.html



  • Es mag ja sein das goto unter C manchmal noch nützlich, aber unter C++ braucht man es nie.



  • CarstenJ schrieb:

    ich finde Pauschalisierungen pauschal schlecht.

    ich halte sogar alle generalisierungen für falsch.

    Denn in der Kernel- bzw. Treiberprogrammierung z.B. wird goto ständig verwendet, und zwar gerade wegen der Übersichtlichkeit. Deiner Aussage nach würde ja kein Kernelprogrammierer etwas auf sich halten... 😉

    korrekt.

    http://ezs.kr.hsnr.de/TreiberBuch/html/sec.technik.html

    da steht

    Im Wesentlichen wird innerhalb des Linux-Kernels goto immer im gleichen Konstrukt verwendet, nämlich um aus einer Funktion auszuspringen und dabei durchgeführte Initialisierungen wieder rückgängig zu machen.

    wer unter c++ sowas macht statt destruktoren zu benutzen, der taugt wenig.
    in c ist goto was anderes.



  • Praetorian schrieb:

    Jeder Programmierer, der etwas auf sich hält, benutzt die Befehle 'break', 'continue' und vor allem 'goto' nicht, aus Lesbarkeits- und Performacegründen. Sie lassen sich allesamt durch Verwendung von Schleifen, if-Anweisungen usw. vermeiden.

    Ähem, wenn du auf break verzichtest, bin ich gespannt, wie du ne switch Anweisung schreibst, oder ist die jetzt auch schon böse?
    Imho haben break und continue ihre daseinsberechtigung.

    MfG

    GPC



  • Man der Mensch meint ja auch ein break&Co würden die Performance verschlechtern...



  • GPC schrieb:

    Ähem, wenn du auf break verzichtest, bin ich gespannt,

    durchs bessere return.

    wie du ne switch Anweisung schreibst, oder ist die jetzt auch schon böse?

    in der tat, switch rutsch ab zu den bösen buben. die hauptaufgaben *waren*

    je nach eingabe was machen
    ersetzt durch nachgucktabellen mit funktionsobjekten (oft mit dem geschenk, daß die tabellen benutzerkonfigurierbar sind)

    je nach extem typ was machen
    ersetzt durch virtuelle funktionen

    Imho haben break und continue ihre daseinsberechtigung.

    continue senkt bei vortests in schleifen die versachachtelungstiefe und macht übersichtlicher. für break sehe ich eher nachteile, es verleitet einen zur strukturierten programmierung.



  • Praetorian schrieb:

    Jeder Programmierer, der etwas auf sich hält, benutzt die Befehle 'break', 'continue' und vor allem 'goto' nicht, aus Lesbarkeits- und Performacegründen. Sie lassen sich allesamt durch Verwendung von Schleifen, if-Anweisungen usw. vermeiden.

    ich habe zufällig lebenden c++-code mit goto drin. wenn ich mich recht erinnere an zwei stellen. ich durchsuche mal die platte.
    würdest du so nett sein und mich in der korrekten verwendung von schleifen unterweisen, indem du meine funktionen, die goto enthalten, umschreibst, daß sie kein goto mehr verwenden und dabei lesbarer und/oder performanter werden?



  • volkard schrieb:

    Praetorian schrieb:

    Jeder Programmierer, der etwas auf sich hält, benutzt die Befehle 'break', 'continue' und vor allem 'goto' nicht, aus Lesbarkeits- und Performacegründen. Sie lassen sich allesamt durch Verwendung von Schleifen, if-Anweisungen usw. vermeiden.

    ich habe zufällig lebenden c++-code mit goto drin. wenn ich mich recht erinnere an zwei stellen. ich durchsuche mal die platte.
    würdest du so nett sein und mich in der korrekten verwendung von schleifen unterweisen, indem du meine funktionen, die goto enthalten, umschreibst, daß sie kein goto mehr verwenden und dabei lesbarer und/oder performanter werden?

    Wird jetzt sehr schwierg ohne den Code zu haben, ist aber nur so ne kleinigkeit am Rande.



  • hab nur zwei gefunden, die in code stecken, den man nachvollziehen kann.
    http://www.volkard.de/siff/goto.rar

    wobei zu bemerken ist, daß der folgende durchaus goto verwendet, um lesbaren code bei großer performance zu erhalten.

    //http://www.geocities.com/acmesofties/wpcq110.htm
    /*
    the following code is the macro expansion of
    
    #define compare(i,j)\
    	if(a[i][0]!=a[j][0] | a[i][1]!=a[j][1]) goto label##i##j;\
    	if(a[i][2]!=a[j][2] | a[i][3]!=a[j][3] | a[i][4]!=a[j][4]) goto label##i##j;\
    	return true;\
    label##i##j:\
    
    int wpc107(int a[5][5])
    {
    	compare(0,1)
    	compare(0,1)
    	compare(0,3)
    	compare(0,4)
    	compare(1,2)
    	compare(1,3)
    	compare(1,4)
    	compare(2,3)
    	compare(2,4)
    	compare(3,4)
    	return false;
    }
    
    //sometimes i used | instead of || or if to expensive jmps.
    */
    
    int wpc107(int a[5][5])
    {
    	if(a[0][0]!=a[1][0] | a[0][1]!=a[1][1]) goto label01;
    	if(a[0][2]!=a[1][2] | a[0][3]!=a[1][3] | a[0][4]!=a[1][4]) goto label01;
    	return true;
    label01:
    	if(a[0][0]!=a[2][0] | a[0][1]!=a[2][1]) goto label02;
    	if(a[0][2]!=a[2][2] | a[0][3]!=a[2][3] | a[0][4]!=a[2][4]) goto label02;
    	return true;
    label02:
    	if(a[0][0]!=a[3][0] | a[0][1]!=a[3][1]) goto label03;
    	if(a[0][2]!=a[3][2] | a[0][3]!=a[3][3] | a[0][4]!=a[3][4]) goto label03;
    	return true;
    label03:
    	if(a[0][0]!=a[4][0] | a[0][1]!=a[4][1]) goto label04;
    	if(a[0][2]!=a[4][2] | a[0][3]!=a[4][3] | a[0][4]!=a[4][4]) goto label04;
    	return true;
    label04:
    	if(a[1][0]!=a[2][0] | a[1][1]!=a[2][1]) goto label12;
    	if(a[1][2]!=a[2][2] | a[1][3]!=a[2][3] | a[1][4]!=a[2][4]) goto label12;
    	return true;
    label12:
    	if(a[1][0]!=a[3][0] | a[1][1]!=a[3][1]) goto label13;
    	if(a[1][2]!=a[3][2] | a[1][3]!=a[3][3] | a[1][4]!=a[3][4]) goto label13;
    	return true;
    label13:
    	if(a[1][0]!=a[4][0] | a[1][1]!=a[4][1]) goto label14;
    	if(a[1][2]!=a[4][2] | a[1][3]!=a[4][3] | a[1][4]!=a[4][4]) goto label14;
    	return true;
    label14:
    	if(a[2][0]!=a[3][0] | a[2][1]!=a[3][1]) goto label23;
    	if(a[2][2]!=a[3][2] | a[2][3]!=a[3][3] | a[2][4]!=a[3][4]) goto label23;
    	return true;
    label23:
    	if(a[2][0]!=a[4][0] | a[2][1]!=a[4][1]) goto label24;
    	if(a[2][2]!=a[4][2] | a[2][3]!=a[4][3] | a[2][4]!=a[4][4]) goto label24;
    	return true;
    label24:
    	if(a[3][0]!=a[4][0] | a[3][1]!=a[4][1]) goto label34;
    	if(a[3][2]!=a[4][2] | a[3][3]!=a[4][3] | a[3][4]!=a[4][4]) goto label34;
    	return true;
    label34:
    	return false;
    }
    


  • Jeder Programmierer, der etwas auf sich hält, benutzt die Befehle 'break', 'continue' und vor allem 'goto' nicht, aus Lesbarkeits- und Performacegründen. Sie lassen sich allesamt durch Verwendung von Schleifen, if-Anweisungen usw. vermeiden.

    Mal so ne Frage: Wie lange programmierst du schon in c++? Für jede switch-anweisung brauchst du den Befehl break, außer du willst es mit tausenden umwegen machen.. Und jedes Programm hat menüs zum auswählen, diese menüs bestehen meistens aus einer switch-anweisung.. also, wenn ich ein großes Programm schreibe benutze ich ziehmlich oft den break-Befehl..



  • Fred123 schrieb:

    Jeder Programmierer, der etwas auf sich hält, benutzt die Befehle 'break', 'continue' und vor allem 'goto' nicht, aus Lesbarkeits- und Performacegründen. Sie lassen sich allesamt durch Verwendung von Schleifen, if-Anweisungen usw. vermeiden.

    Mal so ne Frage: Wie lange programmierst du schon in c++? Für jede switch-anweisung brauchst du den Befehl break, außer du willst es mit tausenden umwegen machen.. Und jedes Programm hat menüs zum auswählen, diese menüs bestehen meistens aus einer switch-anweisung.. also, wenn ich ein großes Programm schreibe benutze ich ziehmlich oft den break-Befehl..

    ähm. das hängt wohl ziemlich stark von der gui-lib ab. ich gehe davon aus, daß den menupunkten methoden zugeordnet werden. und sehe da kein einziges switch.



  • hallo volkrad! Nehmen wir an, ich will ein Programm programmieren, dass ein Menü ausgibt.. Dann würde der Code meiner meinung nach so lauten:

    #include <iostream.h>
    int menu();
    void Dotaskone();
    int main()
    {
         bool exit=false;
         for (;;)
         {
              int choice=menu();
              switch(choice);
              {
                 case (1):
                   Dotaskone();
                  [b] break;[/b]// :D 
                case (2)
                exit=true;
                break;
              }
              if (exit)
              break;
          }
         return 0;
    }
    int menu()
    {
        int choice;
        cout<<" ****Menue***\n\n";
        cout<<"(1)rechteck zeichnen\n";
        cout<<"(2)Beenden\n \n";
        cin>> choice;
        return choice;
    }
    void Dotaskone()
    {
      cout<<" Irgendwas machen..\n";
    }
    


  • Fred123 schrieb:

    Dann würde der Code meiner meinung nach so lauten:

    nicht zwingend. je weiter man die funktionale zerlegung treibt, desto schwächer wird break und desto stärker wird return.

    #include <iostream>
    using namespace std;
    
    int menu() {
    	cout<<" ****Menue***\n\n";
    	cout<<"(1)rechteck zeichnen\n";
    	cout<<"(2)Beenden\n \n";
    	int choice;
    	cin>> choice;
    	return choice;
    }
    
    void Dotaskone() {
    	cout<<" Irgendwas machen..\n";
    }
    
    bool on1(){
    	Dotaskone();
    	return true;
    }
    
    bool on2(){
    	return false;
    }
    
    bool dispatch(){
    	switch(choice){
    		case 1: return on1();
    		case 2: return on2();
    	}
    }
    
    int main() {
    	while(dispatch(menu()))
    		;
    }
    

Log in to reply