goto's verwenden
-
@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).
-
Marc++us schrieb:
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.
nee, das haste falsch verstanden. dieser codegenerator erzeugt codes mit #include "irgendwas.c" darin. warum er's macht weiss ich auch nicht, aber dabei geht's jedenfalls nicht um stacknutzung...
Marc++us schrieb:
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.
auf anhieb fallen mir 2 gründe ein, warum man den eingebauten stack nicht für funktionsaufrufe benutzen darf:
1. der gesamte speicher wird für was anderes benötigt, so dass kein platz mehr für den stack da ist.
2. man nutzt die eingebauten stack-mechanismen der cpu um mit den push/pop instructions spezielle effekte zu erreichen (stackpointer wird z.b. auf 'nen i/o bereich gesetzt und man hat sich eine art DMA gebastelt).
klar, das sind sonderfälle, aber irgendwie treffe ich immer wieder auf so komische sachen...Marc++us schrieb:
Daraus jetzt eine Regel abzuleiten, daß man besser nicht zu viele Funktionsaufrufe in seinen Programmen verwendet erscheint mir mehr als gewagt.
das will ja auch keiner. funktionen sind dann schlecht (zur laufzeit) wenn sie wenig code enthalten und zudem häufig aufgerufen werden. aber in den allermeisten fällen (bei der gigahertz-megabyte-pc-programmierung) spielt das sowieso keine rolle. einverstanden?

-
rüdiger schrieb:
@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.leider muss ich dich entäuschen rüdiger, mein kleines project beinhaltet knapp 50-60 goto's die aber ausschließlich zum verlassen von verschachtelten schleifen genutzt werden, und das project ist ca. 20'000 zeilen c (und ist noch nicht mal fertig).
Freak_Coder schrieb:
for(int i=0; i<10; i++) for(int u=0; u<10; u++) if(array[i][u] == blabla) break; if(array[i][u] == blabla) break;bool run = 1; for(int i=0; i<10 && run; i++) for(int u=0; u<10; u++) if(array[i][u] == blabla) { run = 0; break; }for(int i=0; (i<10) && (array[i][u] != blabla); i++) for(int u=0; (u<10) && (array[i][u] != blabla); u++)ich habe es nicht außprobiert aber soweit ich sehe funktioniert das erste und dritte beispiel doch garnicht...

sorry das ich so spät antworte, war zu lange pennen.
-
pi88el schrieb:
mein kleines project beinhaltet knapp 50-60 goto's ...
obwohl ich goto-befürworter bin, aber das, finde ich, sind schon ziemlich viele...