C: Verschachtelte Ifs oder Gotos

8

Was ist der beste Weg, Ressourcen für ein C Programm zu verwalten? Soll ich eine verschachtelte if-Struktur verwenden oder soll ich goto-Anweisungen verwenden?

Ich bin mir bewusst, dass es viele Tabus über goto Statements gibt. Ich denke jedoch, dass dies für die lokale Ressourcenbereinigung gerechtfertigt ist. Ich habe zwei Proben geliefert. Man vergleicht eine verschachtelte if-Struktur und eine andere verwendet goto-Anweisungen. Ich persönlich finde, dass die goto-Anweisungen den Code leichter lesbar machen. Für diejenigen, die argumentieren könnten, dass die verschachtelte if -Eingabe eine bessere Struktur hervorruft, stellen Sie sich vor, der Datentyp wäre etwas anderes als ein char *, wie ein Windows-Handle. Ich glaube, dass die Struktur nested if mit einer Reihe von CreateFile Funktionen oder jede andere Funktion, die große Mengen an Parametern benötigt.

Dieser Artikel zeigt, dass lokale goto-Anweisungen RAII für C-Code erstellen. Der Code ist ordentlich und einfach zu folgen. Stellen Sie sich das als eine Folge von verschachtelten if Anweisungen vor.

Ich verstehe, dass goto in vielen anderen Sprachen tabu ist, weil es andere Kontrollmechanismen wie try / catch usw. gibt, aber in C scheint es angemessen.

%Vor%

Ich möchte auch Linus Torvalds auf goto Statements im Linux Kernel zitieren.

  

Und manchmal ist die Struktur schlecht und   kommt in den Weg und mit einem "goto"   ist nur viel klarer.

     

Zum Beispiel ist es ziemlich üblich   haben Bedingungen, die nicht NEST.

     

In diesem Fall haben Sie zwei   Möglichkeiten

     
  • benutze goto und sei glücklich, da es die Verschachtelung nicht erzwingt

         

    Dies macht den Code lesbarer,   da macht der code gerade was   Algorithmus sagt, es sollte tun.

  •   
  • duplizieren Sie den Code, und schreiben Sie ihn in einer verschachtelten Form neu, so dass Sie können   benutze die strukturierten Sprünge.

         

    Dies macht oft den Code viel weniger   lesbar, schwieriger zu pflegen und   größer.

  •   

Die Pascal-Sprache ist ein Paradebeispiel   von letzterem Problem. Weil es   hat keine "break" Aussage,   Schleifen in (traditionellem) Pascal enden   sieht oft total scheiße aus, weil   Sie müssen völlig willkürlich hinzufügen   Logik zu sagen "Ich bin jetzt fertig".

Ist goto für das Ressourcenmanagement akzeptabel? Sollte ich verschachtelte if -Anweisungen verwenden oder gibt es einen besseren Weg?

Update: Beispiele für gute Gotos In C

    
Community 10.11.2010, 20:39
quelle

11 Antworten

9

Die Bereinigung mit goto hat den Vorteil, dass es weniger fehleranfällig ist. Das Freigeben jeder einzelnen Ressource, die an jedem einzelnen Rückkehrpunkt zugewiesen wird, kann dazu führen, dass jemand bei Wartungsarbeiten irgendwann nicht mehr aufräumt.

Das heißt, ich zitiere Knuths "Strukturierte Programmierung mit goto Statements":

  

Ich argumentiere für die Eliminierung von go to's in bestimmten Fällen und für ihre Einführung in anderen.

und Knuths Zitat von Dijkstra in demselben Papier:

  

"Bitte fallen Sie nicht in die Falle, zu glauben, dass ich furchtbar dogmatisch bin [das Go to Statement]. Ich habe das unangenehme Gefühl, dass andere eine Religion daraus machen, als ob die konzeptionellen Probleme des Programmierens könnten durch einen einzigen Trick gelöst werden, durch eine einfache Form der Kodierung Disziplin! " [29].

    
ninjalj 10.11.2010, 20:51
quelle
10

Zweifellos war Dijkstra eine beeindruckende Persönlichkeit in der Programmierwelt. Seine Goto Consumedly Harmful Papier war sehr übertrieben. Ja GoTo kann wahllos verwendet werden und kann schädlich sein, aber viele denken, dass GoTo ein absolutes Verbot ist nicht gerechtfertigt. Knuth gab Dijkstra eine sehr gut begründete Widerlegung in: Strukturierte Programmierung mit GO-TOs

Lesen Sie Knuths Papier, Sie werden feststellen, dass Ihr GoTo-Muster eine der guten Anwendungen ist für GoTo.

BTW, Dijkstra ist auch für eine Reihe anderer Dinge sehr zitierbar. Wie wäre es mit:

  • Objektorientierte Programmierung ist eine außergewöhnlich schlechte Idee, die nur in Kalifornien hätte entstehen können.

Dijkstra war ein großer Mathematiker und hat große Beiträge zur Informatik geleistet. Aber ich nicht Ich denke, dass er sich mit dem alltäglichen Zeug beschäftigen musste oder daran interessiert war, 99,99 Prozent davon unsere Programme tun es.

Verwenden Sie GoTo nur mit Grund und Struktur. Benutze sie selten. Aber benutze sie.

    
NealB 10.11.2010 21:14
quelle
10

Wenn Sie goto verwenden, können Sie es vermeiden, komplexen Code zu schreiben, dann verwenden Sie goto .

Ihr Beispiel könnte auch so geschrieben werden (no goto s):

%Vor%     
Nick Dandoulakis 10.11.2010 20:51
quelle
4

Benutze immer einen Goto in jedem Programm, um die Puristen zu ärgern

Das ist meine Philosophie.

Im Ernst, in manchen Fällen ist ein goto sinnvoll, besonders wenn es nur etwas Offensichtliches tut, wie zum Beispiel den Sprung zum allgemeinen Rückkehrcode am Ende einer Funktion.

    
DigitalRoss 10.11.2010 20:43
quelle
3

Persönlich habe ich in der Vergangenheit auf diese Weise goto benutzt. Die Leute hassen es, weil es sie an den Spaghetti-Code erinnert, den sie geschrieben haben, oder weil jemand, der solchen Code geschrieben hat, das Konzept, dass Gotos böse sind, in sie schlägt.

Du könntest wahrscheinlich etwas Anständiges schreiben, ohne zu gehen, klar. Aber es wird in dieser Art von Umständen keinen Schaden anrichten.

    
cdhowie 10.11.2010 20:42
quelle
2

Von zwei Ihrer Alternativen ist Goto natürlich besser und netter. Aber es gibt eine dritte und bessere Alternative: Verwenden Sie Rekursion!

    
Armen Tsirunyan 10.11.2010 20:45
quelle
2

Ich würde den Code anders strukturieren als beide. Wenn ich keinen anderen Grund hätte, etwas anderes zu tun, würde ich den Code wahrscheinlich so schreiben:

%Vor%     
Jerry Coffin 10.11.2010 21:16
quelle
2

Ein sehr großer Unterschied zwischen dem Beispiel in dem Artikel, zu dem du verlinkt hast und dem Code, den du postest, ist, dass deine gotos-Labels <functionName>_<number> sind und ihre goto-Labels cleanup_<thing_to_cleanup> sind.

Sie verwenden goto line_1324 next, und der Code wird bearbeitet, so dass das Label line_1234 in Zeile 47823 ...

steht

Verwenden Sie es wie im Beispiel und achten Sie sehr darauf, den zu lesenden Code zu schreiben.

    
Pete Kirkham 10.11.2010 21:20
quelle
1

Wenn Sie wissen, was Sie tun, und der resultierende Code sauberer und lesbarer aussieht (ich wette, es tut), dann gibt es absolut kein Problem mit GOTOs. Vor allem das Beispiel "Graceful initialization failure recovery", das Sie gezeigt haben, ist weit verbreitet.

Übrigens, wenn Sie strukturierten Code schreiben, der 100 Dinge initialisiert, würden Sie 100 Ebenen der Einrückung benötigen ... was einfach hässlich ist.

    
Mirek Kratochvil 10.11.2010 20:46
quelle
1

In C ist goto oft die einzige Möglichkeit, Cleanup-Code wie C ++ - Destruktoren oder Java finally -Klauseln zu approximieren. Da es wirklich das beste Werkzeug ist, das du für diesen Zweck hast, sage ich, benutze es. Ja, es ist leicht zu missbrauchen, aber auch viele Programmierkonstrukte. Zum Beispiel würden die meisten Java-Programmierer nicht zögern, Ausnahmen auszulösen, aber Ausnahmen sind auch leicht zu missbrauchen, wenn sie für etwas anderes als die Fehlerberichterstattung, wie die Flusskontrolle, verwendet werden. Aber wenn Sie goto explizit zum Zweck der Vermeidung von Cleanup-Code-Duplikation verwenden, können Sie sicher sagen, dass Sie es wahrscheinlich nicht missbrauchen.

Im Linux-Kernel finden Sie viele durchaus sinnvolle Verwendungen von goto .

    
Charles Salvia 10.11.2010 20:56
quelle
0

Ich bevorzuge diese Art der Fehlerbehandlung. Nimmt man D Schnipsel einen Schritt weiter, verwendet es ein allgemeines Goto-Label für die Fehlerbehandlung.

%Vor%     
hopia 30.11.2010 18:25
quelle

Tags und Links