Beispiele für gute Gotos in C oder C++ [closed]

Lesezeit: 10 Minuten

Beispiele fur gute Gotos in C oder C closed
Fizzer

In diesem Thread sehen wir uns Beispiele für gute Verwendungen von an goto in C oder C++. Es ist inspiriert von einer Antwort, die Leute gewählt haben, weil sie dachten, ich mache Witze.

Zusammenfassung (Etikett vom Original geändert, um die Absicht noch klarer zu machen):

infinite_loop:

    // code goes here

goto infinite_loop;

Warum es besser ist als die Alternativen:

  • Es ist spezifisch. goto ist das Sprachkonstrukt, das eine unbedingte Verzweigung bewirkt. Alternativen hängen von der Verwendung von Strukturen ab, die bedingte Verzweigungen mit einer degenerierten Always-True-Bedingung unterstützen.
  • Das Etikett dokumentiert die Absicht ohne zusätzliche Kommentare.
  • Der Leser muss den dazwischenliegenden Code nicht vorzeitig scannen breaks (obwohl es für einen prinzipienlosen Hacker immer noch möglich ist, zu simulieren
    continue mit früh goto).

Regeln:

  • Tu so, als hätten die Gotophoben nicht gewonnen. Es versteht sich, dass das Obige nicht in echtem Code verwendet werden kann, da es gegen die etablierte Sprache verstößt.
  • Gehen Sie davon aus, dass wir alle von „Goto gilt als schädlich“ gehört haben und wissen, dass goto zum Schreiben von Spaghetti-Code verwendet werden kann.
  • Wenn Sie mit einem Beispiel nicht einverstanden sind, kritisieren Sie es allein aus technischen Gründen (‘Weil die Leute goto nicht mögen’ ist kein technischer Grund).

Mal sehen, ob wir wie Erwachsene darüber reden können.

Bearbeiten

Diese Frage scheint nun erledigt. Es generierte einige qualitativ hochwertige Antworten. Danke an alle, besonders an diejenigen, die mein kleines Loop-Beispiel ernst genommen haben. Die meisten Skeptiker waren besorgt über den fehlenden Blockbereich. Wie @quinmars in einem Kommentar betonte, können Sie immer Klammern um den Schleifenkörper legen. Das merke ich nebenbei an for(;;) und while(true) Geben Sie Ihnen die Klammern auch nicht kostenlos (und das Weglassen kann zu ärgerlichen Fehlern führen). Jedenfalls verschwende ich nicht noch mehr von deiner Denkkraft auf diese Kleinigkeit – ich kann mit dem Harmlosen und Idiomatischen leben for(;;) und while(true) (ebenso gut, wenn ich meinen Job behalten will).

Wenn ich die anderen Antworten betrachte, sehe ich, dass viele Leute das sehen goto als etwas, das man immer anders umschreiben muss. Natürlich können Sie a vermeiden goto durch Einführung einer Schleife, eines zusätzlichen Flags, eines Stapels von verschachtelten ifs, oder was auch immer, aber warum nicht überlegen, ob goto ist vielleicht das beste Werkzeug für den Job? Anders ausgedrückt, wie viel Hässlichkeit sind die Menschen bereit, zu ertragen, um zu vermeiden, dass eine eingebaute Sprachfunktion für den beabsichtigten Zweck verwendet wird? Meiner Ansicht nach ist selbst das Hinzufügen einer Flagge ein zu hoher Preis. Ich mag es, wenn meine Variablen Dinge in den Problem- oder Lösungsdomänen darstellen. „Nur um a zu vermeiden goto‘ schneidet es nicht ab.

Ich akzeptiere die erste Antwort, die das C-Muster für die Verzweigung zu einem Bereinigungsblock lieferte. IMO, das ist das stärkste Argument für a goto aller geposteten Antworten, sicherlich wenn man es an den Verrenkungen misst, die ein Hasser durchmachen muss, um es zu vermeiden.

  • Ich verstehe nicht, warum die Gotophobes nicht einfach “#define goto report_to_your_supervisor_for_re_education_through_labour” oben in der Include-Datei des Projekts vorschreiben. Wenn es immer falsch ist, mach es unmöglich. Ansonsten ist es manchmal richtig…

    – Steve Jessop

    30. Oktober 2008 um 1:36 Uhr

  • “kann nicht in echtem Code verwendet werden”? Ich verwende es immer dann in “echtem” Code, wenn es das beste Werkzeug für den Job ist. „Etablierte Redewendung“ ist ein schöner Euphemismus für „blinde Dogmatik“.

    – Dan Formen

    18. August 2010 um 15:58 Uhr

  • Ich stimme zu, dass “goto” nützlich sein kann (es gibt unten großartige Beispiele), aber ich stimme Ihrem spezifischen Beispiel nicht zu. Eine Zeile mit der Aufschrift „goto infinite_loop“ klingt so, als würde sie bedeuten „Gehe zu dem Teil des Codes, an dem wir mit der Endlosschleife beginnen werden“, wie in „initialize(); set_things_up(); goto infinite_loop;“ wenn Sie wirklich vermitteln wollen, dass „die nächste Iteration der Schleife beginnen, in der wir uns bereits befinden“, was völlig anders ist. Wenn Sie versuchen, eine Schleife zu erstellen, und Ihre Sprache über Konstrukte verfügt, die speziell für Schleifen entwickelt wurden, verwenden Sie diese zur Verdeutlichung. while(true) {foo()} ist ziemlich eindeutig.

    – Josch

    21. Dezember 2010 um 19:00 Uhr

  • Ein großer Nachteil Ihres Beispiels ist, dass nicht ersichtlich ist, welche andere Stellen im Code können entscheiden, zu diesem Label zu springen. Eine “normale” Endlosschleife (for (;;)) hat keine überraschenden Einstiegspunkte.

    – jalf

    5. Januar 2011 um 19:56 Uhr

  • @György: ja, aber das ist kein Einstiegspunkt.

    – jalf

    5. März 2011 um 10:36 Uhr

1646882411 146 Beispiele fur gute Gotos in C oder C closed
Greg Rogers

Hier ist ein Trick, den ich von Leuten gehört habe. In freier Wildbahn habe ich es allerdings noch nie gesehen. Und es gilt nur für C, weil C++ RAII hat, um dies idiomatischer zu tun.

void foo()
{
    if (!doA())
        goto exit;
    if (!doB())
        goto cleanupA;
    if (!doC())
        goto cleanupB;

    /* everything has succeeded */
    return;

cleanupB:
    undoB();
cleanupA:
    undoA();
exit:
    return;
}

  • Was ist daran falsch? (abgesehen davon, dass Kommentare keine Zeilenumbrüche verstehen) void foo() { if (doA()) { if (doB()) { if (doC()) { /* alles erfolgreich */ return; } rückgängig machenB (); } UndoA(); } Rückkehr; }

    – Artelios

    29. Oktober 2008 um 4:21 Uhr

  • Die zusätzlichen Blöcke verursachen unnötige Einrückungen, die schwer lesbar sind. Es funktioniert auch nicht, wenn sich eine der Bedingungen in einer Schleife befindet.

    – Adam Rosenfield

    29. Oktober 2008 um 4:42 Uhr

  • Sie können eine Menge dieser Art von Code in den meisten Low-Level-Unix-Dingen sehen (wie zum Beispiel im Linux-Kernel). In C ist das IMHO das beste Idiom für die Fehlerbehebung.

    – David Cournapeau

    29. Oktober 2008 um 7:25 Uhr

  • Wie bereits erwähnt, verwendet der Linux-Kernel diesen Stil die ganze Zeit.

    – CesarB

    29. Oktober 2008 um 11:00 Uhr

  • Sehen Sie sich nicht nur den Linux-Kernel in den Windows-Treiberbeispielen von Microsoft an, und Sie werden dasselbe Muster finden. Im Allgemeinen ist dies ein C-Weg zur Behandlung von Ausnahmen und sehr nützlich :). Normalerweise bevorzuge ich nur 1 Label und in wenigen Fällen 2. 3 kann in 99% der Fälle vermieden werden.

    – Ilja

    29. Oktober 2008 um 12:37 Uhr

Die klassische Notwendigkeit für GOTO in C ist wie folgt

for ...
  for ...
    if(breakout_condition) 
      goto final;

final:

Es gibt keine einfache Möglichkeit, verschachtelte Schleifen ohne goto zu verlassen.

  • Meistens, wenn dieser Bedarf auftritt, kann ich stattdessen eine Rückgabe verwenden. Aber Sie müssen kleine Funktionen schreiben, damit es so funktioniert.

    – Darius Bacon

    29. Oktober 2008 um 5:50 Uhr

  • Ich stimme Darius definitiv zu – refaktorisieren Sie es in eine Funktion und kehren Sie stattdessen zurück!

    – metao

    29. Oktober 2008 um 6:13 Uhr

  • @metao: Bjarne Stroustrup ist anderer Meinung. In seinem Buch zur C++-Programmiersprache ist dies genau das Beispiel für eine „gute Verwendung“ von goto.

    – Paercebal

    29. Oktober 2008 um 9:45 Uhr

  • @Adam Rosenfield: Die ganzes Problem Mit goto, hervorgehoben von Dijkstra, bietet die strukturierte Programmierung verständlichere Konstrukte. Code schwerer lesbar zu machen, um Goto zu vermeiden, beweist, dass der Autor diesen Aufsatz nicht verstanden hat …

    – Steve Jessop

    30. Oktober 2008 um 0:43 Uhr

  • @Steve Jessop: Nicht nur, dass die Leute den Aufsatz missverstanden haben, die meisten der „No go to“-Kultisten verstehen den historischen Kontext nicht, in dem er geschrieben wurde.

    – NUR MEINE richtige MEINUNG

    23. April 2011 um 9:09 Uhr

Beispiele fur gute Gotos in C oder C closed
Fizzer

Hier ist mein nicht dummes Beispiel (von Stevens APITUE) für Unix-Systemaufrufe, die durch ein Signal unterbrochen werden können.

restart:
    if (system_call() == -1) {
        if (errno == EINTR) goto restart;

        // handle real errors
    }

Die Alternative ist eine degenerierte Schleife. Diese Version liest sich wie Englisch “Wenn der Systemaufruf durch ein Signal unterbrochen wurde, starten Sie ihn neu”.

  • Dieser Weg wird zum Beispiel verwendet, wenn der Linux-Scheduler ein solches Goto hat, aber ich würde sagen, es gibt sehr wenige Fälle, in denen Rückwärts-Gotos akzeptabel sind und im Allgemeinen vermieden werden sollten.

    – Ilja

    29. Oktober 2008 um 12:38 Uhr

  • @Amarghosh, continue ist nur ein goto in einer Maske.

    – jball

    3. Juni 2010 um 16:31 Uhr

  • @jball … hmm … um der Argumentation willen, ja; Gut lesbaren Code können Sie mit goto und Spaghetti-Code mit Continue erstellen. Letztendlich hängt es von der Person ab, die den Code schreibt. Der Punkt ist, dass man sich mit goto leichter verirrt als mit Continue. Und Anfänger verwenden normalerweise den ersten Hammer, den sie bekommen, für alle Probleme.

    – Amarghosch

    4. Juni 2010 um 4:06 Uhr

  • @Amarghosch. Ihr ‘verbesserter’ Code entspricht nicht einmal dem Original – im Erfolgsfall wiederholt er sich für immer.

    – Fizzer

    4. Juni 2010 um 12:05 Uhr

  • @fizzer oopsie … es werden zwei benötigt else breaks (eines für jedes ifs), um es gleichwertig zu machen.. was soll ich sagen … goto oder nicht, dein Code ist nur so gut wie du 🙁

    – Amarghosch

    4. Juni 2010 um 12:15 Uhr

Wenn Duffs Gerät kein goto benötigt, sollten Sie das auch nicht! 😉

void dsend(int count) {
    int n;
    if (!count) return;
    n = (count + 7) / 8;
    switch (count % 8) {
      case 0: do { puts("case 0");
      case 7:      puts("case 7");
      case 6:      puts("case 6");
      case 5:      puts("case 5");
      case 4:      puts("case 4");
      case 3:      puts("case 3");
      case 2:      puts("case 2");
      case 1:      puts("case 1");
                 } while (--n > 0);
    }
}

obigen Code aus Wikipedia Eintrag.

Knuth hat eine Arbeit “Strukturierte Programmierung mit GOTO-Anweisungen” geschrieben, die Sie zB von bekommen können Hier. Da findest du viele Beispiele.

  • Dieses Papier ist damit veraltet, es ist nicht einmal lustig. Knuths Annahmen dort halten einfach nicht mehr.

    – Konrad Rudolf

    29. Juni 2009 um 15:17 Uhr

  • Welche Annahmen? Seine Beispiele sind heute für eine prozedurale Sprache wie C (er gibt sie in einem Pseudocode) so real wie damals.

    – zvrba

    29. Juni 2009 um 17:08 Uhr

1646882412 245 Beispiele fur gute Gotos in C oder C closed
vergänglich

Sehr gewöhnlich.

do_stuff(thingy) {
    lock(thingy);

    foo;
    if (foo failed) {
        status = -EFOO;
        goto OUT;
    }

    bar;
    if (bar failed) {
        status = -EBAR;
        goto OUT;
    }

    do_stuff_to(thingy);

OUT:
    unlock(thingy);
    return status;
}

Der einzige Fall, den ich je benutze goto dient zum Vorwärtsspringen, normalerweise aus Blöcken heraus und niemals in Blöcke hinein. Dadurch wird ein Missbrauch vermieden do{}while(0) und andere Konstrukte, die die Verschachtelung erhöhen und gleichzeitig lesbaren, strukturierten Code beibehalten.

  • Dieses Papier ist damit veraltet, es ist nicht einmal lustig. Knuths Annahmen dort halten einfach nicht mehr.

    – Konrad Rudolf

    29. Juni 2009 um 15:17 Uhr

  • Welche Annahmen? Seine Beispiele sind heute für eine prozedurale Sprache wie C (er gibt sie in einem Pseudocode) so real wie damals.

    – zvrba

    29. Juni 2009 um 17:08 Uhr

Beispiele fur gute Gotos in C oder C closed
Mitch Weizen

Ich habe im Allgemeinen nichts gegen Gotos, aber mir fallen mehrere Gründe ein, warum Sie sie nicht für eine Schleife verwenden möchten, wie Sie sie erwähnt haben:

  • Es schränkt den Umfang nicht ein, daher werden alle temporären Variablen, die Sie darin verwenden, erst später freigegeben.
  • Es schränkt den Umfang nicht ein und kann daher zu Fehlern führen.
  • Der Bereich wird nicht eingeschränkt, daher können Sie dieselben Variablennamen später in zukünftigem Code im selben Bereich nicht wiederverwenden.
  • Es schränkt den Umfang nicht ein, daher haben Sie die Möglichkeit, eine Variablendeklaration zu überspringen.
  • Die Leute sind daran nicht gewöhnt und es wird Ihren Code schwerer lesbar machen.
  • Verschachtelte Schleifen dieses Typs können zu Spaghetti-Code führen, normale Schleifen führen nicht zu Spaghetti-Code.

  • ist inf_loop: {/* Schleifenkörper */} goto inf_loop; besser? 🙂

    – Quinmare

    29. Oktober 2008 um 9:39 Uhr

  • Punkte 1-4 sind zweifelhaft für dieses Beispiel auch ohne hosenträger. 1 Es ist eine Endlosschleife. 2 Zu vage, um darauf einzugehen. 3 Der Versuch, eine gleichnamige Variable in einem einschließenden Gültigkeitsbereich zu verstecken, ist eine schlechte Übung. 4. Ein Rückwärts-Goto kann eine Deklaration nicht überspringen.

    – Fizzer

    30. Oktober 2008 um 7:44 Uhr

  • 1-4 wie bei allen Endlosschleifen haben Sie normalerweise eine Art Unterbrechungsbedingung in der Mitte. Sie sind also anwendbar. Bei einem bakward goto kann eine Deklaration nicht übersprungen werden … nicht alle gotos sind rückwärts …

    – Brian R. Bondy

    30. Oktober 2008 um 23:36 Uhr

985890cookie-checkBeispiele für gute Gotos in C oder C++ [closed]

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy