Ich weiß, dass jeder GOTO hasst und niemand empfiehlt es. Aber darum geht es nicht. Ich möchte nur wissen, welcher Code der schnellste ist:
die goto
Schleife
die while
Schleife
die for
Schleife
Im Allgemeinen werden for
und while
Schleifen auf die gleiche Weise wie goto
kompiliert, so dass es normalerweise keinen Unterschied macht. Wenn Sie Zweifel haben, können Sie alle drei ausprobieren und sehen, was länger dauert. Wahrscheinlichkeiten sind, dass Sie einen Unterschied nicht messen können, selbst wenn Sie eine Milliarde Schleifen wiederholen.
Wenn Sie diese Antwort , Sie werden sehen, dass der Compiler genau den gleichen Code für for
, while
und goto
generieren kann (nur in diesem Fall gab es keine Bedingung) .
Schreiben Sie kurze Programme, dann tun Sie das:
%Vor%Analysieren Sie die Ausgabe und sehen Sie, ob es einen Unterschied gibt. Stellen Sie sicher, ein gewisses Maß an Unvorhersehbarkeit einzuführen, so dass der Compiler das Programm nicht zu nichts optimiert.
Die Compiler optimieren diese trivialen Probleme auf hervorragende Weise. Ich schlage vor, dass ich mir keine Sorgen machen muss, und konzentriere mich darauf, was dich als Programmierer produktiver macht.
Geschwindigkeit und Effizienz sind eine großartige Sache, um sich darum zu sorgen, aber 99% der Zeit, die die Verwendung von geeigneten Datenstrukturen und Algorithmen erfordert ... keine Sorge darüber, ob ein for
schneller ist als ein while
oder ein goto
usw.
Ich persönlich bin nicht gut genug, um mit Stevens Arbeit zu argumentieren, also werde ich es nicht versuchen. goto kann für leistungsbezogene Probleme nützlich sein, aber die Grenzen von wenn das ist, sind ziemlich streng.
Es ist wahrscheinlich sowohl Compiler, Optimierer als auch architekturspezifisch.
Zum Beispiel ist der Code if(--i) goto loop;
ein konditionaler Test gefolgt von einem unbedingten Zweig . Ein Compiler könnte einfach den entsprechenden Code erzeugen oder er wäre schlau genug (obwohl ein Compiler, der nicht über so viel Intelligenz verfügte, möglicherweise nicht viel wert ist), um eine einzelne bedingte Verzweigung zu erzeugen. while(i--)
andererseits ist bereits eine bedingte Verzweigung auf der Quellenebene, so dass die Übersetzung in eine bedingte Verzweigung auf der Maschinenebene einfacher sein kann, unabhängig von der Komplexität der Compilerimplementierung oder des Optimierers.
Am Ende ist der Unterschied wahrscheinlich klein und nur relevant, wenn sehr viele Iterationen erforderlich sind, und die Art, wie Sie diese Frage beantworten sollten, besteht darin, den Code für das spezifische Ziel und den Compiler (und die Compilereinstellungen) zu erstellen Interesse, und entweder den resultierenden Code auf Maschinenebene zu inspizieren oder die Ausführungszeit direkt zu messen.
In Ihren Beispielen dominiert printf () in der Schleife jedes Timing; Etwas einfacher in der Schleife würde Beobachtungen der Unterschiede einfacher machen. Ich würde eine leere Schleife vorschlagen und dann i
volatile
deklarieren, um zu verhindern, dass die Schleife auf nichts optimiert wird.
Solange Sie den gleichen Kontrollfluss wie eine normale Schleife erzeugen, kann und wird fast jeder vernünftige Compiler den gleichen Code erzeugen, egal ob Sie for
, while
usw. dafür verwenden.
Sie können etwas mit goto
erreichen, aber normalerweise nur, wenn Sie einen Kontrollfluss erzeugen, den eine normale Schleife einfach nicht (zumindest sauber) ausführen kann. Ein typisches Beispiel ist das Springen in die Mitte einer Schleife, um ein Schleifen-and-Half-Konstrukt zu erhalten, das die normalen Schleifenanweisungen der meisten Sprachen (einschließlich Cs) nicht sauber bereitstellen.
Es sollte keinen signifikanten Unterschied zwischen allen Loops und dem Goto geben. Außer der Idee wird dieser Compiler wahrscheinlich nicht versuchen, die GOTO-Dinge überhaupt zu optimieren.
Und es ist nicht sehr sinnvoll, Compiler-generierte Sachen in Loops zu optimieren. Es ist sinnvoller, den Code innerhalb der Schleife zu optimieren oder die Anzahl der Iterationen zu reduzieren.
Es gibt einige Nischenvertikale, in denen goto immer noch als Standardpraxis verwendet wird, von einigen sehr sehr schlauen Leuten und es gibt keine Voreingenommenheit gegen goto in diesen Einstellungen. Ich arbeitete früher in einer simulationsorientierten Firma, in der der gesamte lokale Fortran-Code Unmengen von GOTOS enthielt, das Team war sehr schlau und die Software arbeitete nahezu fehlerfrei.
Also können wir das Verdienst von goto beiseite lassen, und wenn die Frage nur darin besteht, die Schleifen zu vergleichen, dann tun wir dies durch Profilieren und / oder Vergleichen des Assembler-Codes. Allerdings enthält die Frage auch Aussagen wie printf usw. Sie können sich nicht wirklich über die Optimierung der Schleifensteuerungslogik unterhalten. Wie bereits erwähnt, erzeugen die gegebenen Schleifen sehr ähnliche Maschinencodes.
Alle bedingten Verzweigungen werden in Pipeline-Prozessorarchitekturen sowieso als "genommen" (wahr) betrachtet, bis die Decodierungsphase, zusätzlich zu kleinen Schleifen, die normalerweise so erweitert werden, dass sie ohne Schleifen sind. Also, in Übereinstimmung mit Harpers obigen Punkt, ist es unrealistisch, dass goto bei der einfachen Schleifenkontrolle irgendeinen Vorteil hat (genauso wie für oder während sie keinen Vorteil gegenüber einander haben). GOTO macht normalerweise in mehreren verschachtelten Schleifen oder mehreren verschachtelten ifs Sinn, wenn die zusätzliche Bedingung, die von goto in JEDEN der verschachtelten Schleifen oder verschachtelten ifs geprüft wird, suboptimal ist.
Wenn Sie eine Suchoperation in einer einfachen Schleife optimieren, ist die Verwendung eines Sentinals manchmal effektiver als alles andere. Im Wesentlichen können Sie durch Hinzufügen eines Dummy-Werts am Ende des Arrays vermeiden, dass zwei Bedingungen (Array-Ende und gefundener Wert) als nur eine Bedingung (Wert gefunden) überprüft werden, und das speichert Cmp-Vorgänge intern. Ich bin mir nicht bewusst, ob Compiler das automatisch tun oder nicht.
Tags und Links c loops performance goto