goto's verwenden
-
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.
-
Daniel E. schrieb:
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.
Halt die Frage, was man als eklig empfindet..
-
Hilfsstrukturen einzuführen, die man nur einmal benutzt, ist wenigstens nicht besonders elegant ... ob ein goto eleganter ist? Keine Ahnung.
-
Marc++us schrieb:
Die Anwendung würde ich gerne sehen, wo man #include "code.c" braucht und keine Funktion verwenden kann...
eine anwendung wäre z.b. ein code, der den prozessorstack nicht verändern darf (aus welchem grund auch immer). manche codegeneratoren, z.b. dieser hier: http://www.cs.vu.nl/~eliens/documents/libero/lrintr.htm machen sowas.
-
net schrieb:
Marc++us schrieb:
Die Anwendung würde ich gerne sehen, wo man #include "code.c" braucht und keine Funktion verwenden kann...
eine anwendung wäre z.b. ein code, der den prozessorstack nicht verändern darf (aus welchem grund auch immer). manche codegeneratoren, z.b. dieser hier: http://www.cs.vu.nl/~eliens/documents/libero/lrintr.htm machen sowas.
Du sprichst komischerweise immer nur von Sonderfällen. "Wenn ein Funktionsaufruf zu teuer ist", "wenn man den Stack nicht verändern darf" etc. Dann ist ein goto meinetwegen auch in Ordnung. Aber das ist ja überhaupt nicht die Frage und für 99,99% der Programmierer in dem Forum auch wenig interessant.
Beim µC und Embedded-Systemen kann so etwas schon mal vorkommen. Das sind dann außnahme Situationen. Dafür muss man kein goto rechtfertigen, weil es in dem Fall vielleicht das vernünftigste Mittel ist. Ich will goto ja gar nicht dogmatisch ablehnen.
Es geht doch darum, das die Benutzung von goto normalerweise zu unübersichtlichen Code führt und eine Aufteilung in viele kleine Funktionen den Code leserlicher macht. Das ist eben ein typischer "Anfänger-Fehler", besonders wenn man einen Basic (oder gar Assembler) Hintergrund hat.
Auch bei Daniel Es Beispiel kann ein goto besser sein, als eine Hilfsstruktur oä. Das muss man eben abwiegen. Aber in 99,99% der Fälle ist es wahrscheinlich nicht nur unsinnig, sondern schadhaft.
-
net schrieb:
manche codegeneratoren, z.b. dieser hier: http://www.cs.vu.nl/~eliens/documents/libero/lrintr.htm machen sowas.
Leider kann ich mir den Quellcode nicht ansehen, da der DL nicht funktioniert, aber ich würde schon gerne den Grund dafür kennen, warum ein Codegenerator den Stack nicht verändern darf... oder der vom Generator erzeugte Code.
Daß man den Stack nicht verändern kann, riecht doch schon sehr extrem nach Embedded Programmierung oder Microcontroller, und selbst da ist's eine Ausnahme. Selbst in einer ISR auf einem µC kann man üblicherweise den Stack so zurichten wie man will.
Daraus jetzt eine Regel abzuleiten, daß man besser nicht zu viele Funktionsaufrufe in seinen Programmen verwendet erscheint mir mehr als gewagt.
-
Wenn ich mir so durchlese was manche Leute als für Vorstellungen und Ansichten haben, dann stelle ich mir ernsthaft die Frage, ob ich wirklich in die IT-Industrie möchte.
Ich hoffe doch, dass nur die Hobby-Programmierer so drauf sind (auch wenn thedailywtf.com was anderes sagt).