Gast
#3737526
Hallo, warum soll ich goto nicht nutzen? Danke
|
Anzeige
|
Warum goto vermeiden
Gast
#3737526
Hallo, warum soll ich goto nicht nutzen? Danke BloedeFrage schrieb: > Hallo, warum soll ich goto nicht nutzen? Ich würde sagen, zu diesem Thema findest du bereits jedem Menge Informationen und Diskussionen im Netz. Hast du schon alle gelesen? Wo sind noch offene Detailfragen?
Gast
#3737596
1. weils auch ohne geht 2. weils ohne besser geht 3. weils mit schlechter geht 4. weils keiner braucht 5. wers trotzdem benutzt sollte sich über seine Herangehensweise Gedanken machen, seine Fehler selber suchen und eventuell mal über eine andere Sprache nachdenken, die einen von vornherein durch das schlichte "goto-nicht-vorhanden-sein" vor derartigen Irrwegen bewahrt
Gast
#3737602
BloedeFrage schrieb: > Hallo, warum soll ich goto nicht nutzen? Wer fordert das von dir? > Danke Bitte.
Gast
#3737605
Sämtliche Leute die mir bisher programmieren beigebracht haben
Gast
#3737613
BloedeFrage schrieb: > Sämtliche Leute die mir bisher programmieren beigebracht haben Wie viele haben dir das programmieren beigebracht? Welche Programmiersprachen hast du dabei erlernt? Haben diese Leute die Forderung - goto nicht zu verwenden - begründet? Wie wurde die Forderung begründet? Wie alt bist du? Welchen Schulabschluss hast du? Hast du einen Hochschulabschluss? Wenn ja, welchen Anschluss hast?
Gast
#3737623
Dieses Dogma hält sich deshalb so gut, weil es deutlich einfacher ist, zu verlagen, es nicht zu benutzen, als zu verstehen, wie man es richtig benutzt. Gernationen von Programmierern haben deshalb nicht einmal versucht zu verstehen, wie man es richtig benutzt. Es lohnt sich, die diversen Abhandlungen azuschauen und auch mal einen Blick in den Linux-Kernel zu werfen anstatt goto unbegründet zu verteufeln. In der Tat gibt es wenige gute Anwendungsszenarien für goto, aber es gibt sie! BloedeFrage schrieb: > Hallo, warum soll ich goto nicht nutzen? Weil die Erfahrung lehrt, dass so etwas bei jemandem der es nicht kann, ganz schnell zu unwartbarem Spaghetticode führt. Es gibt Einsatzfälle für goto. Aber das sind ganz spezielle Fälle. Einfach mit goto wie wild drauf los programmieren, führt fast immer ins Chaos. Speziell bei Anfängern. Ein Profi hingegen braucht so etwas nicht zu fragen. Der weiß, wann ein goto tatsächlich die einfachste und beste Lösung ist und wann nicht.
Gast
#3737636
BloedeFrage schrieb: > Sämtliche Leute die mir bisher programmieren beigebracht haben Als Anfänger tut man gut dran, es zu vermeiden, da es eine relativ hohe Gefahr birgt, damit schlechten Code zu schreiben. Es gibt aber Fälle, in denen es durchaus sinnvoll ist. Wer das generell meidet wie der Teufel das Weihwasser, der hat's aber nicht wirklich verstanden.
Gast
#3737650
Klaus Kaiser schrieb: > Dieses Dogma hält sich deshalb so gut, weil es deutlich einfacher ist, > zu verlagen, es nicht zu benutzen, als zu verstehen, wie man es richtig > benutzt. Allerdings. Wenn man sich Richtlinien wie MISRA anschaut, findet man noch jede Menge weitere Regeln, die genau in die selbe Kerbe schlagen. > Gernationen von Programmierern haben deshalb nicht einmal versucht zu > verstehen, wie man es richtig benutzt. Das sehe ich auch immer wieder. Die schlagen die Hände schon über dem Kopf zusammen, wenn man goto nur erwähnt, aber wenn man genauer nachhakt, merkt man, daß sie eigentlich gar nicht wissen, warum. Es werden halt nur die Sprüche derer, von denen man die Sprache gelernt hat, nachgeplappert, ohne sie zu verstehen.
Gast
#3737675
GENAU aus dem Grund habe ich die Frage gestellt. Und habe jetzt, zumindest ein paar, brauchbare Einschätzungen erhalten. Es geht also vor allem um die Lesbarkeit, welche durch (schwer nachzuvollziehende) Sprünge leidet. Richtig?
Gast
#3737680
Falsch. Google mal nach "goto statement considered harmfull".
Gast
#3737693
>In der Tat gibt es wenige gute Anwendungsszenarien für goto, aber es >gibt sie! Was wäre denn ein gutes Beispiel? Das Abbrechen einer verschachtelten Schleife oder Fehlerbehandlung?
Gast
#3737701
BloedeFrage schrieb: > GENAU aus dem Grund habe ich die Frage gestellt. Und habe jetzt, > zumindest ein paar, brauchbare Einschätzungen erhalten. Es geht also vor > allem um die Lesbarkeit, welche durch (schwer nachzuvollziehende) > Sprünge leidet. Richtig? Mal eine kleine Beispielfunktion (Arduino), die 2 zurückliefert, wenn man 1 als Parameter übergibt und die 1 zurückliefert, wenn man 2 als Parameter übergibt und ansonsten eine Fehlermeldung auf Serial ausgibt.
Schöner geht es doch nun wirklich nicht, oder? ;-) Bei den uralten BASIC Dialekten ist das mit dem GOTO übrigens dadurch gekommen, dass pro Programmzeile (das waren Interpretersprachen mit numerierten Zeilen) nach einer if-Abfrage nur ein einzelner Befehl ausgeführt werden konnte. Für if-Zweige gab es keine Codeblöcke. Daher war es dann eben oft so, dass als einziger erlaubter Befehl nach einer positiven if-Bedingung ein GOTO-Sprung gemacht wurde. Seit alle Programmiersprachen Codeblöcke nach einer if-Bedingung erlauben (selbst BASIC kann das seit Jahrzehnten) ist GOTO relativ überflüssig. Nützlich ist "goto" ist heute noch ggf. beim Herausspringen aus mehrfach verschachtelten for-Schleifen, wenn man aus einer der inneren for-Schleifen direkt herausspringen möchte. Jürgen schrub: >Nützlich ist "goto" ist heute noch ggf. beim Herausspringen aus mehrfach >verschachtelten for-Schleifen, wenn man aus einer der inneren >for-Schleifen direkt herausspringen möchte. Das ist aber keine gute Idee, da mit GOTO herauszuspringen, weil das jede Menge "Trümmer" hinterläßt. Bei Bascom gibt es für solche Aktionen diese Befehle: EXIT FOR EXIT DO EXIT WHILE EXIT SUB EXIT FUNCTION ******************************************************************* Exit Paul
Gast
#3737749
NoGoTo schrieb: > 3. weils mit schlechter geht Ich kenne das auch so. Jeder erzählt es. Mich würde mal eine wirkliche Abhandlung darüber interessieren wieso es damit schlechter sein soll. Wirklich Nachteile und nicht nur den Millionsten der sage "das darf man nicht". Paul Baumann schrieb: > Das ist aber keine gute Idee, da mit GOTO herauszuspringen, weil das > jede Menge "Trümmer" hinterläßt. > > Bei Bascom gibt es für solche Aktionen diese Befehle: > EXIT FOR Und aus einer dreifach geschachtelten for-Schleife nach diesem Muster springst Du mit Deinem Bascon dann wie heraus?
Hast Du das "verschachtelt" in meinem Beitrag überlesen oder kannst Du bei Deinem BASCOM aus einer Dreifachverschachtelung vielleicht rausspringen indem Du schreibst EXIT FOR FOR FOR ??? Natürlich gibt es auch unter C-Möglichkeiten, eine dreifach verschachtelte for-Schleife vorzeitig abzubrechen, ohne goto zu verwenden. Aber diese mehrfach verschachtelte for-Schleife wäre einer der wenigen Fälle, wo es mit goto eleganter als ohne goto möglich ist. 132 schrieb: > NoGoTo schrieb: >> 3. weils mit schlechter geht > > Ich kenne das auch so. Jeder erzählt es. Mich würde mal eine wirkliche > Abhandlung darüber interessieren wieso es damit schlechter sein soll. Der von Jürgen weiter oben gepostete Spaghetti Code reicht dir noch nicht? Was ist leichter zu verstehen? Der Code da oben, oder
oder für die, die sich am Mehrfach-Return stören
Leider ist Jürgens Code von weiter oben (der zur Abschreckung gedacht war) so ziemlich genau das, was bei einem durchschnittlichen Anfänger rauskommt, wenn er hemmungslos goto verwendet. Er will bestehenden Code nicht verändern, muss ihn aber erweitern, also springt er mit einem goto quer durch die Gegend. Diese ganzen Konstrukte wie 'if', 'for', 'while', 'else' laufen letzten Endes immer intern auf einen goto hinaus. Nur verpacken sie das ganze so, dass dieser implizite goto in einer strukturierten Form vorkommt und in geordneten Bahnen verläuft. Quasi eine freiwillige Selbstbeschränkung. Gerade Schleifenkonstrukte sind dafür ja ein Paradebeispiel: Im Grunde alles durch andere Konstrukte und einem goto ersetzbar. BloedeFrage schrieb: > Hallo, warum soll ich goto nicht nutzen? Weil es viel bessere Lösungen gibt. http://en.wikipedia.org/wiki/COMEFROM ;-)
Gast
#3737883
und PICs haben 'GOTO' (statt JMP) im ASM-Befehlssatz! Jürgen frug: >Und aus einer dreifach geschachtelten for-Schleife nach diesem Muster >springst Du mit Deinem Bascon dann wie heraus? Bascom -mit "M" wie Matratze Pass gut auf: Das ist nicht mein Bascom, es ist keine spezielle Version für mich erstellt worden. Solche Konstrukte wie Deines verwende ich nicht. Insofern ist mir das vollkommen Titte! Es ging darum, auf geordnete Weise aus einer Schleife herauszuspringen. Paul
Gast
#3737895
Es gab früher mal so etwas wie ein Struktogramm, und dort konnte man gotos halt nicht einpflegen zudem ist die Programmierung nicht "strukturiert" Im Grunde spricht aber nichts gegen gotos. Ich verwende die auch des öfteren für Fehlerhandlingsituationen (wie oben auch schon von jemand anderen angedeutet).
Gast
#3737931
Es ist manchmal einfacher (zu lesen) von mehrerer Stellen aus mit GOTO an (eine) bestimmte Stele springen, als bsp.weise etliche verschachtelte IFs zu benutzen.
Gast
#3737936
Gozo schrieb: >>In der Tat gibt es wenige gute Anwendungsszenarien für goto, aber es >>gibt sie! > Was wäre denn ein gutes Beispiel? Das Abbrechen einer verschachtelten > Schleife oder Fehlerbehandlung? Genau das sind die beiden sinnvollen Anwendungsfälle, die ich kenne. Paul Baumann schrieb: > Das ist aber keine gute Idee, da mit GOTO herauszuspringen, weil das > jede Menge "Trümmer" hinterläßt. Was für Trümmer soll das denn hinterlassen? Paul Baumann schrieb: > Es ging darum, auf geordnete Weise aus einer Schleife herauszuspringen. Eben nicht. Du antworetest auf: Jürgen schrub: >Nützlich ist "goto" ist heute noch ggf. beim Herausspringen aus mehrfach >verschachtelten for-Schleifen, wenn man aus einer der inneren >for-Schleifen direkt herausspringen möchte. Einfach nur aus einer Schleife rausspringen kann man in C auch mit break.
Gast
#3737979
Gozo schrieb: > Was wäre denn ein gutes Beispiel? Das Abbrechen einer verschachtelten > Schleife oder Fehlerbehandlung? Gerade bei der Fehlerbehandlung verwende ich regelmäßig gotos, wenn nachher noch "aufgeräumt" werden muß. Allerdings gehört Fehlerbehandlung immer noch zu den Dingen, zu denen ich wenig Informationen über sinnvolle Konzepte lesen konnte. So sieht bei mir z.B. eine typische Fehlerbehandlung aus:
Was man auf den ersten Blick sieht, ist daß hier das Paradigma des "nur ein Rückkehrpunkt" massiv verletzt ist - andererseits ist das ja auch keine "normale" Funktion, bei der das Funktionsergebnis wichtig ist, sondern wo nur die Nebenwirkungen gewollt werden und der Rückgabeparameter nur Hilfsmittel der Kontrolle ist. Sprich: Ich kenne oft kein besseres Mittel zur Fehlerbehandlung als gotos. Viele Grüße W.T. [EDIT: OK, gerade hier ist der einzige Zweck des gotos die Wiedererkennbarkeit, da die einzige Sprungquelle direkt davor liegt.]
Gast
#3737990
Rolf Magnus schrieb: > Jürgen schrub: >>Nützlich ist "goto" ist heute noch ggf. beim Herausspringen aus mehrfach >>verschachtelten for-Schleifen, wenn man aus einer der inneren >>for-Schleifen direkt herausspringen möchte. > > Einfach nur aus einer Schleife rausspringen kann man in C auch mit > break. Aber nicht, wie er schreib, bei einer "mehrfach verschachtelten for-Schleife". Es ist weitgehend egal. In PIC assembler muss man es andauernd verwenden. Wichtig ist dass der Quelltext gut lesbar ist, wie dies erreicht wird ist egal. Rolf Magnus schrieb: > Gozo schrieb: >>>In der Tat gibt es wenige gute Anwendungsszenarien für goto, aber es >>>gibt sie! >> Was wäre denn ein gutes Beispiel? Das Abbrechen einer verschachtelten >> Schleife oder Fehlerbehandlung? > > Genau das sind die beiden sinnvollen Anwendungsfälle, die ich kenne. In Java sind diese beiden Probleme durch labeled Statments gelöst. Damit kann man mit break <label> beliebig verschachtelte Schleifen oder Blöcke verlassen. Das break <label> stellt – wie auch alle anderen Kontrollkonstrukte auch – ein verstecktes, aber eingeschränktes (und damit weniger böses) goto dar und macht das goto fast völlig überflüssig, weswegen es aus Java längst hinausgeschmissen wurde. Auch andere etwas neuere Programmiersprachen bieten ähnliche Konstrukte zum Verlassen verschachtelter Schleifen und zur übersichtlicheren Fehlerbehandlung. Es gibt aber noch ein paar weitere Anwendungen für Gotos. Zwei Beispiele, die mir gerade einfallen: - State-Machines: Hier werden mitunter Gotos für schnelle Zustandswechsel ohne eine explizite Zustandsvariable verwendet. - Source-to-Source-Compiler: Die Generierung von goto-durchsetztem Spaghetti-Code ist oft einfacher als die Strukturierung des Codes in while…endwhile, for…endfor, if…else…endif usw. Da der generierte Code ohnehin nicht dazu gedacht ist, von Menschen gelesen zu werden, stellt das keinen großen Nachteil dar.
Gast
#3738097
>Es ist weitgehend egal. In PIC assembler muss man es andauernd >verwenden. Da sollte es JMP heissen, nicht Goto. Sowas macht nur die von PIC!
Gast
#3738118
Rolf Magnus schrieb: > Was für Trümmer soll das denn hinterlassen? Das kommt auch wesentlich auf den Compiler an. Soweit ich weiss gibt es welche, die einem Goto automatisch (magisch) Aufräumcode voranstellen, es gibt aber auch welche, die einen aus einer Prozedur herausspringen lassen ohne den Stack zu bereinigen. Nicht umsonst gibt es in manchen Firmen qualitätssichernde Vorschriften wie etwa die, dass eine Funktion immer nur einen Einsprungspunkt und einen Endpunkt haben darf. In Assembler darf man sowieso alles, aber das ist keine Entschuldigung für schlecht strukturierte Programme. Und wenn man tricksen muss, etwa aus einem Unterprogramm direkt in ein anders springen, sollte man das sorgfältig kommentieren, aber noch besser es sein lassen. Georg Yalu X. schrieb: > In Java sind diese beiden Probleme durch labeled Statments gelöst. Damit > kann man mit break <label> beliebig verschachtelte Schleifen oder Blöcke > verlassen. Das break <label> stellt – wie auch alle anderen > Kontrollkonstrukte auch – ein verstecktes, aber eingeschränktes (und > damit weniger böses) goto dar und macht das goto fast völlig > überflüssig, weswegen es aus Java längst hinausgeschmissen wurde. .. in Java sollte man break labels auch vermeiden wenn moeglich, weil es eben so nah am goto ist ;) Braucht man alles auch nicht wenn der Code sauber strukturiert ist, d.h. keine geschachtelten Schleifen bzw. keine anderen Kontrollstrukturen die direkt geschachtelt sind. Jede Schleife in eine eigene Methode, dann reicht in 99% der Faelle ein return.
Gast
#3738143
Mladen G. schrieb: > Braucht man alles auch nicht wenn der Code sauber strukturiert ist, d.h. > keine geschachtelten Schleifen bzw. keine anderen Kontrollstrukturen die > direkt geschachtelt sind. wenn man z.b Bilddaten mit X und Y bearbeitet. Dann sind geschachtelten Schleifen sehr wohl sinnvoll. Dafür extra eine Funktion aufrufen ist wohl nicht immer die Lösung. Außerdem ist eine extra Funktion auch keine Lösung, dann damit hat man genau das gleiche Problem
mit einer Funktion geht das auch nicht sinnvoller
dann kann ich auch mit einer extra variable arbeiten
für mich die die goto lösung die übersichtlichste und vermutlich auch die schnellste. Die Version mit der Extra Funktion ist die langsamste. Warum sollte man auf ein Sprachfeature verzichten, wenn man damit kurzen und schnellen code schreiben kann? Peter II schrieb: > wenn man z.b Bilddaten mit X und Y bearbeitet. Dann sind geschachtelten > Schleifen sehr wohl sinnvoll. Dafür extra eine Funktion aufrufen ist > wohl nicht immer die Lösung. KOmmt auf den Kontext an. Bei C etc. pp. mag das stimmen. Bei Java gibt es absooluit keinen Grtund ekine eigenen Methode dafuer zu nehmen, siehe auch "Clean Code" von Bob Martin dazu.. Peter II schrieb: > für mich die die goto lösung die übersichtlichste und vermutlich auch > die schnellste. > Die Version mit der Extra Funktion ist die langsamste. In C vielleicht.. in Java sieht das anders aus, da kommt der JIT/Hotspot besser mit kleinen Methoden zurecht. Ist aber voreilige Optimierung, in Java sollte definitiv der Quellcode im vordergrund stehen, nicht Pseudo Optimierungen. Peter II schrieb: > Warum sollte man auf ein Sprachfeature verzichten, wenn man damit kurzen > und schnellen code schreiben kann? Weil der Code schlecht zu lesen und warten ist.
Gast
#3738153
Mladen G. schrieb: >> Warum sollte man auf ein Sprachfeature verzichten, wenn man damit kurzen >> und schnellen code schreiben kann? > > Weil der Code schlecht zu lesen und warten ist. klar wenn du nie goto verwendest, kannst du den code auch nicht warten. Bei anderen gehört es einfach zur Sprache dazu und ist genauso normal wie der "?" Operator, und diese Leute haben kein Problem mit der Wartung. Peter II schrieb: > klar wenn du nie goto verwendest, kannst du den code auch nicht warten. > Bei anderen gehört es einfach zur Sprache dazu und ist genauso normal > wie der "?" Operator, und diese Leute haben kein Problem mit der > Wartung. Ich hatte noch nie das Beduerfnis goto zu verwenden, wozu auch? Sehe keinen einzigen nutzen darin, ausser dass es den Code schlechter macht. "Andere Leute" finden zB. auch PHP und Perl super, ich nicht.
Gast
#3738176
Mladen G. schrieb: > Ich hatte noch nie das Beduerfnis goto zu verwenden, wozu auch? > Sehe keinen einzigen nutzen darin, ausser dass es den Code schlechter > macht. Das es eine code schlechter macht ist ja Ansichtssache. Andere finden ihn dann besser. Wenn du aber jeden code mit goto als grundsätzlich schlecht Betrachtest macht eine weiter Diskussion keine sinn. http://eli.thegreenplace.net/2009/04/27/using-goto-for-error-handling-in-c/ Peter II schrieb: > Wenn du aber jeden code mit goto als grundsätzlich schlecht Betrachtest > macht eine weiter Diskussion keine sinn. Wie gesagt, im Kontext Java ist das immer (fast) immer schlecht, wobei es ja in Java nur die break Labels gibt und ich diese dann verteufele ;) goto ist in Java zwar reserviert, aber nciht belegt. Dein Link zeigt C, da ist das eben ein anderer Kontext. Wobei man jetzt auch argumentieren kann, dass das Auslagern von verschachtelten Schleifen in eigene Funktionen den ansonsten knackigen Algorithmus zerfleddert und er dadurch wiederum schlecht zu lesen und zu warten ist. Kommt wohl auf den Einzelfall an ... Mladen G. schrieb: > .. in Java sollte man break labels auch vermeiden wenn moeglich, weil es > eben so nah am goto ist ;) > ... > Jede Schleife in eine eigene Methode, dann reicht in 99% der Faelle ein > return. Für mein Empfinden ist ein Return aus einer (evtl. verschachtelten) Schleife schlechterer Stil als ein entsprechender Break, da letzterer zwar eine oder mehrere Blockgrenzen, der Return aber zusätzlich noch eine Methodengrenze überspringt. Dass des von vielen Java-Programmieren anders gesehen wird, liegt vielleicht auch daran, dass die break-<label>-Anweisungen und die Labels selbst syntaktisch stark den Gotos bzw. den Labels in C ähneln. Semantisch gesehen sind aber wesentlich restriktiver. PHP verwendet beim break statt der Labels eine Zahl, die angibt, um wieviele Ebenen beim Verlassen von verschachtelten Schleifen nach oben gesprungen wird. Das gefällt mir syntaktisch besser, hat aber den Nachteil, dass man bei langen Schleifenrümpfen nicht sofort sieht, welche der Schleifen denn nun tatsächlich beendet werden und welche noch weiterlaufen. Yalu X. schrieb: > Für mein Empfinden ist ein Return aus einer (evtl. verschachtelten) > Schleife schlechterer Stil als ein entsprechender Break, da letzterer > zwar eine oder mehrere Blockgrenzen, der Return aber zusätzlich noch > eine Methodengrenze überspringt. Wenn die Methode nur diese eine Schleife enthaelt, ist es "sauberer". Die Clean Code Regeln aus Bob Martins Buch machen Sinn wenn man sie alle im Kontext sieht. zB ist es gar kein Problem mehrere returns in einer einzigen Methode zu haben, denn Methoden haben auch sehr kurz zu sein, wieviele returns bekommt man in 3-5 Zeilen unter? ;) Alexander B. schrieb: > Wobei man jetzt auch argumentieren kann, dass das Auslagern von > verschachtelten Schleifen in eigene Funktionen den ansonsten knackigen > Algorithmus zerfleddert und er dadurch wiederum schlecht zu lesen und zu > warten ist. Kommt wohl auf den Einzelfall an ... Mag sein dass es im Einzelfall anders ist, aber dier generelle Regel nur eine einzige "Einrueckung" pro Methode zu haben funzt, Ausnahmen fuer spezielle Algorythmen (die man in Java mit der Lupe suchen muss) kann man ja machen. In der Batch-Programmierung ist das gang und gäbe, weil man dort ohne GOTO nicht weiterkommt: http://www.robvanderwoude.com/goto.php Spaghetti mit Tomatensoße
Gast
#3738271
BloedeFrage schrieb: > GENAU aus dem Grund habe ich die Frage gestellt. Und habe jetzt, > zumindest ein paar, brauchbare Einschätzungen erhalten. Es geht also vor > allem um die Lesbarkeit, welche durch (schwer nachzuvollziehende) > Sprünge leidet. Richtig? Nein, nicht wirklich. Es gab historische Gründe. Zu der Zeit, als C aufkam, gab es massenweise Homecomputer, auf denen ein residenter Basic-Interpreter werkelte. Eher "richtige" Computer, wo CP/M drauf lief, waren teuer bis unerschwinglich. Der Weg, den man also auf seinem Homecomputer einschlagen mußte, um irgend ein Programm zum Laufen zu bekommen war also, erstmal Basic zu lernen und zu benutzen. Basic war eine Sprache, die sehr zeilennummernorientiert war. Also z.B. ein Unterprogramm-Aufruf hieß z.B. GOSUB 1000 wobei 1000 die Zeilennummer war. Genauso ging es mit GOTO 1005 oder so. Schau dir mal ELIZA.BAS an, dann verstehst du wie das damals ging. Für ganz einfache Programme war das alles ausreichend, aber nicht für größere komplexere Programme. Man kann in C auch so ähnlich schreiben wie in Basic - genauso, wie man auch z.B. in fast jeder Programmiersprache so ähnlich schreiben kann wie in Fortran.. ;-) Nun, um nun all die jungen Basic-gewöhnten angehenden Programmiereriche umzuerziehen, wurde eben damals die Parole formuliert, in C niemals goto zu benutzen, bei Strafe der Exkommunikation oder Kielholen oder was auch immer. Ja, DAMALS. Mittlerweile kennt kaum ein junger Strolch noch Basic, aber der Drill der damaligen Gulags hält sich weiter in den Köpfen und hat abenteuerliche Workarounds beschert. Ein häufiges Beispiel ist while(1). Eigentlich ist sowas wie while ja eine bedingte Schleife und auch genau dafür gedacht. Daß man sie mit while(1) quasi entartet hat, bloß um ein simples goto zu vermeiden, zeigt, was für Verrenkungen sich immer bei dogmatischem Drill einstellen. Laß dich also von beschränkten Dogmatikern nicht einschüchtern, sondern verwende eben auch goto, wo es einen echten Sinn ergibt. Das ist tatsächlich nicht wirklich häufig, aber es kommt vor. Ein simples Beispiel ist die Grundschleife bei Mikrocontrollern: int main (void) { initialisiere(); immerzu: machedies(); machedas(); machenochwas(); goto immerzu; } Wenn man das mit einem while(1) formuliert, dann meckern manche Compiler, daß main ja gar kein Ergebnis zurückgibt - zu Recht (im Prinzip). Also findet man bei solchen Strategen nach der Endlosschleife noch ein return 0 oder so, um den schieren Formalismus zu befriedigen. W.S. Mladen G. schrieb: > zB ist es gar kein Problem mehrere returns in einer einzigen Methode zu > haben, denn Methoden haben auch sehr kurz zu sein, wieviele returns > bekommt man in 3-5 Zeilen unter? ;) Einverstanden. Wenn die Methoden aber so kurz sind, muss man verschachtelte Schleifen auf mehrere Methoden verteilen (das hast du weiter oben wahrscheinlich auch so gemeint). Wie kannst du dann aber von der innersten Schleife (die sich in einer Methode befindet) aus die äußerste (in einer anderen Methode) verlassen? Das geht doch nur dadurch, dass jede Methode ein entsprechendes Flag zurückgibt, das in der Schleife der aufrufenden Methode abgefragt und ggf. weitergereicht wird, und das über mehrere Ebenen. Das wird doch beliebig kompliziert und trägt sicher nicht zur besseren Lesbarkeit des Programms bei. Oder wie würdest du bspw. folgende Methode in drei Methoden mit jeweils einer Schleife aufdröseln?
Georg schrieb: > Rolf Magnus schrieb: >> Was für Trümmer soll das denn hinterlassen? > > Das kommt auch wesentlich auf den Compiler an. Soweit ich weiss gibt es > welche, die einem Goto automatisch (magisch) Aufräumcode voranstellen, > es gibt aber auch welche, die einen aus einer Prozedur herausspringen > lassen ohne den Stack zu bereinigen. > > Nicht umsonst gibt es in manchen Firmen qualitätssichernde Vorschriften > wie etwa die, dass eine Funktion immer nur einen Einsprungspunkt und > einen Endpunkt haben darf. > > In Assembler darf man sowieso alles, aber das ist keine Entschuldigung > für schlecht strukturierte Programme. Und wenn man tricksen muss, etwa > aus einem Unterprogramm direkt in ein anders springen, sollte man das > sorgfältig kommentieren, aber noch besser es sein lassen. > > Georg Zeig mir mal einen modernen Compiler der es erlaubt aus der Prozdur (Pascal?) herauszuspringen. Das geht in C schon mal gar nicht. In Embedded C bekommst du sofort einen Absturz wenn der Stack nicht stimmt. Ausserdem koennen C funktionen durchaus viele Endpunkte haben- je nach Bedingung wird einer zuerst aktiv. Dadurch wird der Quelltext kuerzer z.b.
kannste in dem Fall auch
verwenden, aber es ist nur ein Beispiel, vielleicht ist Wert obskur und soll bereits in der Funktion umgesetzt werden. Denk mal darueber nach:
bewirkt auch nichts anderes als eine for schleife. Mit dem Unterschied dass bei for die Bedingung zuerst abgefragt wird, hier wird der code innerhalb zumindest einmal abgearbeitet. ausserdem, wenn du es aus irgeneinem obskurem Grund willst, kannst du den Wiederholpunkt auch noch von woanders anspringen. Das kann schon Sinn machen wenn du es mit Bitmaps zu tun hast, die u.U. alignment erfordern, u.U. aber auch nicht. Mit FOR musst du dann den Code nochmal wiederholen. Ja klar mit zu vielen GOTOs versaust du dein Programm (zumindest den Quelltext). Yalu X. schrieb: > Wenn die Methoden aber so kurz sind, muss man verschachtelte Schleifen > auf mehrere Methoden verteilen (das hast du weiter oben wahrscheinlich > auch so gemeint). > > Wie kannst du dann aber von der innersten Schleife (die sich in einer > Methode befindet) aus die äußerste (in einer anderen Methode) verlassen? > Das geht doch nur dadurch, dass jede Methode ein entsprechendes Flag > zurückgibt, das in der Schleife der aufrufenden Methode abgefragt und > ggf. weitergereicht wird, und das über mehrere Ebenen. > > Das wird doch beliebig kompliziert und trägt sicher nicht zur besseren > Lesbarkeit des Programms bei. Oder wie würdest du bspw. folgende Methode > in drei Methoden mit jeweils einer Schleife aufdröseln? > >
Das ist ein Beispiel, bei dem es wohl besser waere es nicht in einzelne Methoden aufzuteilen. Muss aber ehrlich dazu sagen, dass ich dieses Konstrukt in 14 Jahren als Hauptberuflicher Java Entwickler noch nie brauchte. Mit ist schon klar dass es wohl immer Ausnahmen geben wird, deswegen sehe ich auhc kein Problem mit einer Regel die sagt: "break labels sollten vermieden werden", weil es eben in den meisten Faellen wahr ist. Ein aus meiner Sicht wichtiger Aspekt ist (neben der in einigen oben beschriebenen Fällen der besseren Lesbarkeit und klareren Struktur) goto erlaubt, kritischen Code sehr kompakt und sehr effizient zu schreiben bzw. zu kompilieren. Dabei geht es z.B. darum, dass der resultierende Code möglichst kurz ist (Cache footprint) und der wahrscheinlichste Codepfad sehr geradlinig ohne Sprünge abläuft (Prefetch queue / branch prediction). Ein beliebter Trick ist dabei eben, in eine geradlinige (Assebler-) Codesequenz an beliebiger Stelle mit Goto einspringen zu können. Dafür ist goto ein gutes Hilfsmittel, aber dafür gibt es noch andere Tricks (likely/unlikely bedingungen) und andere "angeblich" sehr böse sachen (switch/case fallthrough) Peter II schrieb: > bool doExit = false; > for( x ... ) { > for( y ... ) { > if ( ... ) { > doExit = true; > break; > } > if ( doExit ) > break; > } je nachdem wie die schleifen aufgebaut sind (z.b. eine matrix durchlaufen oder sowas in der richtung) könnte man das ganze auch dadurch abbrechen, dass man anstatt doExit = true die einzelnen abbruchbedingungen der schleifen quasi erzwingt. sowas in der art
bitte nicht auf die konstanten festnageln - es geht ja nur ums prinzip... Mladen G. schrieb: > Das ist ein Beispiel, bei dem es wohl besser waere es nicht in einzelne > Methoden aufzuteilen. > > Muss aber ehrlich dazu sagen, dass ich dieses Konstrukt in 14 Jahren als > Hauptberuflicher Java Entwickler noch nie brauchte. Ein ganz ähnliches Konstrukt ergibt sich, wenn man bspw. in einem mehrdimensionalen Array ein Element mit einer bestimmten Eigenschaft suchen möchte. So etwas läuft einem doch öfter über den Weg. Manche Programmiersprachen bzw. Bibliotheken bieten aber auch die Möglichkeit, verschachtelte Schleifen wie die obigen eben zu büglen, so dass nur noch eine einzelne Schleife übrig bleibt, die mit einem gewöhnlichen break verlassen werden kann. In python sähe das bspw. so aus:
Das Stichwort dazu lautet "Iteratoren", die es m.W. in ähnlicher Form auch in der Java-Bibliothek gibt. Vielleicht kann man dort mit den leidigen verschachtelten Schleifen ähnlich verfahren wie in Python. Will man auch noch auf den break verzichten, der ja immer noch ein Bisschen Goto-Charakter hat, kann man das Ganze in Python auch als Generator-Comprehension schreiben:
Diese Schreibweise hat Python übrigns von Haskell geerbt, wo das Genze noch etwas kompakter geschrieben wird:
Da in Haskell die Liste ein Spezialfall einer Monade ist, kann man die List-Comprehension (der Teil nach "head") auch im Monadenstil schreiben:
Das sieht zwar nicht arg viel anders aus als das vorherige Beispiel, aber die mit <-[0..9] endenen Zeilen sind jetzt getrennte Actions. Da sie alle gleich aussehen, liegt es nahe, sie in eine Art Schleife zu packen:
Die Zahl der verschachtelten Schleifen im ursprünglichen Java-Code taucht hier in der zweiten Zeile als numerische Konstante (3) auf. Man kann sie durch eine Variable n ersetzen, wenn man gleichzeitig dafür sorgt, dass die Funktion condition und die Summe in der letzten Zeile mit einer variablen Zahl von Operanden klar kommen. Das geschieht am einfachsten dadurch, dass man die Variablen x, y und z zusammen durch eine Liste (xs) mit n Elementen ersetzt. Das sieht dann so aus:
Dieser Code tut tatsächlich im Wesentlichen das Gleiche wie der ursprüngliche Java-Code:
Er ist aber kürzer und die Anzahl der verschachtelten impliziten Schleifen ist variabel und kann über das Funktionsargument n gesteuert werden. Der break im Java-Programm verbirgt sich implizit in der head-Funktion, die das erste Element der durch den do-Block erzeugten Liste zurückgibt. Da die restlichen Elemente nirgend benutzt werden, werden sie auch nicht berechnet, was einem Abbruch der verschachtelten Suchschleife gleichkommt. Nicht nur der break, sondern auch die expliziten For-Schleifen sind verschwunden. Sie sind irgendwo in die Tiefen der Laufzeitbibliothek verlagert worden, ähnlich wie die impliziten Gotos der For-Schleifen in Java in den Maschinencode der VM verlagert werden, wo sie niemanden stören. Diese Beispiel zeigt, dass man explizite Sprünge (Gotos) schrittweise durch weniger explizite Sprünge ersetzen kann, bis am Schluss auf Quellcodeebene nur noch linearer Code übrig bleibt. Linearer Code ist das genaue Gegenteil vom Spaghetti-Code und deswegen nur minimal fehleranfällig. Bei der schrittweisen Umwandlung wurde sogar ohne großen Zusatzaufwand noch Funktionalität hinzugewonnen (Iteration von n statt nur 3 Variablen), die sich mit den klassischen aus der strukturierten Programmierung bekannten Konstrukten nur schwer realisieren lässt. Trotzdem hat es sich ein Verückter nicht nehmen lassen, auch für Haskell ein Goto nachzurüsten: http://hackage.haskell.org/package/GotoT-transformers-1.0/docs/Control-Monad-Trans-Goto.html Ich vermute aber, dass es sich hier primär um einen Fall von "Und es geht doch" ohne allzu viel praktischen Nutzen handelt. Auch für Python hat jemand so ein Proof-of-Concept-Goto entwickelt. Es spricht immerhin für die Mächtigkeit einer Programmiersprache, wenn so etwas mit gewöhnlichen Sprachmitteln ohne Manipulation des Compilers und ohne die Verwendung eines speziell dafür angefertigten Präprozessors möglich ist.
Gast
#3738741
Martin schrieb: > Es gab früher mal so etwas wie ein Struktogramm Die Nassi-Shneiderman-Diagramme haben aus gutem Grund ihren Eingang in die DIN (DIN 66261) gefunden. Versuch da mal ein "goto" rein zu strukturieren. Ein "Goto" machte fast jede Programmstruktur unberechenbar (Ausnahme vielleicht das "Exit"). @Yalu Ginge das auch mit einem range von 10000? Oder anders gefragt: Muss das product im Speicher Platz haben?
Gast
#3738797
Hallo Konrad, Konrad S. schrieb: > Ginge das auch mit einem range von 10000? Jaein. > Oder anders gefragt: Muss das product im Speicher Platz haben? Jaein. Wenn man es wie Yalu mit der range()-Funktion macht, dann müssen die drei von range zurückgegebenen Listen Platz im Speicher haben. product() würde dann aber trotzdem jeweils über die Listen iterieren und einen Iterator bereitstellen, der jeweils nur das akutelle Ergebnis berechnet, und dann braucht auch nur das aktuelle Ergebnis Platz im Speicher. Dem geneigten Pythonista steht deswegen neben der Funktion range() auch noch die Funktion xrange() zur Verfügung, die nicht wie range() eine Liste, sondern einen Iterator zurückgibt. Wenn man also anstelle von Yalus Code
benutzt, dann wird bei jedem Aufruf von product() immer nur das aktuelle Ergebnis berechnet und im Speicher allokiert. HTH, Karl Ja klar nun starte ich Eclipse oder MPLABX auf meinem 1GB netbook, was sind schon 1GB, warte 3 Minuten, die Eingabe ist blockiert, irgenwann gehts dann sogar, umschalten, naja, warte 20 Sekunden. desgleichen mit Skype und Web hotmail. Die brauchen FLASH und Silverlight um dir Werbung zu zeigen die du immer wieder aus versehen anclickst. Ist dass nicht so eine Art GOTO gegen deinen Willen? Du clickst die Scroll Leiste, aber der Browser macht ein neues Fenster auf mit Skype Werbungsseiten die nutzlos sind und die du schon 20 mal gesehen hast. Aber sei dir gewiss, der Source code enthaelt garantiert kein einziges GOTO. Also ersteht es irgenwie wieder auf? Ach ja, liegt wohl daran das 1GB zuwenig Speicher ist. Mit GOTO ist es halt so eine Sache, es ist ein linearer Ablauf, du befindest dich bei Punkt A, und gehst zu Punkt B aus irgeneinem Grund. Im realen Leben kannst du das nicht vermeiden, oder wie ist da der objektorientierte Ansatz?
Gast
#3738836
Anfänger sollten möglichst viel goto verwenden. Denen sollte man die Schleifen gar nicht beibringen. Wenn viele goto's verwendet werden, dann habe ich einen sicheren Arbeitsplatz bis zur Rente. Ansonsten bin ich die letzten 25 Jahre goto-frei ausgekommen, und ich habe wirklich viel Code geschrieben. Naja wie schon oben beschrieben gibt es Anwendungen wo Goto sinnvoll ist. Für so richtig eleganten Code braucht man aber natürlich das Comefrom, das in vielen Sprachen drin ist.
Gast
#3738863
Daniel F. schrieb: > je nachdem wie die schleifen aufgebaut sind (z.b. eine matrix > durchlaufen oder sowas in der richtung) könnte man das ganze auch > dadurch abbrechen, dass man anstatt doExit = true die einzelnen > abbruchbedingungen der schleifen quasi erzwingt. Das ist aber ein fieser Trick, den ich nicht nutzen würde, nur um goto vermeiden zu können. Man spart sich zwar die unschöne Statusvariable, die man auf jeder Ebene nochmal extra abfragen muss, aber elegant ist das auch nicht. Genau das ist die Sache: Man kann goto immer irgendwie vermeiden, aber das Ziel sollte nicht sein, goto um jeden Preis wegzubekommen, sondern guten Code zu schreiben. Und manchmal (wenn auch selten) ist der mit goto besser. Mike schrieb: > Ein "Goto" machte fast jede Programmstruktur unberechenbar (Ausnahme > vielleicht das "Exit"). Was soll denn daran unberechnenbar sein? goto springt ja nicht willkürlich irgendwo hin. @Takao K.: Bekanntlich ist goto ja auch für die globale Erwärmung, die Vogelgrippe und natürlich dafür, daß in China so viele Reissäcke umfallen, verantwortlich. Konrad S. schrieb: > @Yalu > Ginge das auch mit einem range von 10000? Oder anders gefragt: Muss das > product im Speicher Platz haben? Karl hat schon fast alles dazu geschrieben. Um über alle Tripel in product(range(10000), range(10000), range(10000)) zu iterieren, braucht man also Speicherplatz für 3·10000=30000 Elemente. Karl Käfer schrieb: > Wenn man also anstelle von Yalus Codeproduct > > (xrange(10), xrange(10), xrange(10)) > > benutzt, dann wird bei jedem Aufruf von product() immer nur das > aktuelle Ergebnis berechnet und im Speicher allokiert. Das stimmt (leider) nicht ganz. Zum einen ist in Python 3 range das, was in Python 2 xrange war. Es liefert also keine Liste, sondern ein Objekt, aus dem sich ein Iterable gewinnen lässt, das unabhängig vom Argument nur wenig Speicher belegt. xrange ist deswegen in Python 3 obsolet. Wenn man die range-Funktion von Python 2 benötigt, kann man diese mit list(range(n)) nachbilden. Zum anderen (und jetzt kommt das "leider") erzeugt die product-Funktion aus jedem der Argumente erst einmal eine Liste. Zumindest beim ersten Argument ist das für mich nicht ganz nachvollziehbar, da dieses Iterable nur ein einziges Mal durchlaufen wird und es deswegen keine Vorteile bringt, die einzelnen Werte zu speichern. Deswegen darf auch keines der Argumente unbegrenzt iterieren, obwohl das beim ersten Argument (das der äußersten Schleife entspricht) schon manchmal wünschenswert wäre und in anderen Sprachen, wie z.B. Haskell auch tatsächlich möglich ist. Dort liefert
bzw.
wie erwartet die endlose Liste
Eine Produktfunktion für Python, deren Speicherbedarf unabhängig von der Größe der übergebenen Iterables ist und die damit auch mit endlosen Iterables zurechtkommt, könnte in ihrer einfachsten Form so aussehen:
Sie ist aber im Vergleich zum Original langsamer, da dieses nicht in Python, sondern in C programmiert ist.
Gast
#3739078
Moin, sind ja ganz schön gruselige Goto Konstrukte, die hier aufschlagen. Jürgen S. schrieb: > void nestedFor() > { > for (int i=0;i<255;i++) > { > for (int j=0;j<255;j++) > { > for (int k=0;k<255;k++) > { > if (i==100 && j==20 && k==2) goto ende; > } > } > } > ende: ; > } Wozu brauchts an der Stelle ein Goto?
schein mir an der Stelle übersichtlicher zu sein, da ich nicht noch extra einem Goto folgen muss um festzustellen, dass aus der Funktion gesprungen wird. Bei der zweiten Variante ist es sofort ersichtlich. Walter Tarpan schrieb: > // anderer Code hier > if (status!=0) > goto error; > > return status; // = 0 > > error: > I2C_reset(EEPROM_I2C_DEVICE); > return status; > }
Wäre an der Stelle auch zu übersichtlich und lesbar (am Rande, status ist als Name schlecht gewählt :) W.S. schrieb: > int main (void) > { initialisiere(); > immerzu: > machedies(); > machedas(); > machenochwas(); > goto immerzu; > } > > Wenn man das mit einem while(1) formuliert, dann meckern manche > Compiler, daß main ja gar kein Ergebnis zurückgibt - zu Recht (im > Prinzip). Also findet man bei solchen Strategen nach der Endlosschleife > noch ein return 0 oder so, um den schieren Formalismus zu befriedigen. Sollte der Compiler nicht bei dir auch meckern? du hast ja immerhin genau so eine Funktion, die einen Rückgabewert erwartet, der du keinen lieferst. An der Stelle ist es aber warscheinlich egal, welches Konstrukt man verwendet ob while(true) oder for(;;) oder goto. Gegen Goto spricht nur die Andersartigkeit der Klammersetzung. Diese ist ja beim Goto einzigartig. So ein Konstrukt gibt es ja in C sonst nicht. Ich meine:
Zweiteres ist man normalerweise nicht gewohnt und muss genauer hin schauen. Das stört den Lesefluss doch erheblich. Besonders wenn man Goto normalerweise nicht benutzt. Goto wird leider überwiegend verwendet um schlechtes Design zu kaschieren. Wenn man mein unbedingt ein Goto zu brauchen, sollte man lieber erst mal ein Refactoring anstoßen und erst wenn das nicht hilft Goto einsetzen. Grüße, nicht"Gast" schrieb: > if (status != 0) > { > I2C_reset(EEPROM_I2C_DEVICE); > } > return status; > Wäre an der Stelle auch zu übersichtlich und lesbar (am Rande, status > ist als Name schlecht gewählt :) genau sowas (aber in einer etwas anderen Form) kann lästige auswirkungen haben. nehmen wir folgende Code-sequenz, erstmal in der "optimalen" Variante ohne Fehlerbehandlung:
schäön sequentiell, keine Sprünge die dir die Pipeline flushen, da kann er wie auf dem geraden Autobahnstück mit 300 Sachen drüberbrettern. nun kommt die lästige Fehlerbehandlung:
ist schon überhaupt nicht mehr geradlinig, dauernde Sprünge (die man aber mit likely() etwas entschärfen kann), aber, und das ist den wenigsten bewusst: cleanup() wird schlimmstenfalls vom compiler viermal inline eingesetzt, damit vervierfacht sich der ICache-Footprint! (ncoh schlimmer und unübersichtlicher wirds wenn ich nicht eine cleanup() habe, sondern drei oder mehr verschiedene die je nachdem wie weit er gekommen ist, aufgerufen werden müssen oder auch nicht) natürlich kann man das auch anders schreiben:
Das inline-problem ist zwar weg, aber übersichtlicher ists auch nciht, speziell wenn ich nicht drei sondern mehr solcher if()s habe bin ich irgendwann am rechten Bildschirmrand... verschiedene Cleanups sind auch schwer unterzubringen, und sequentiell ists auch nicht gerade... Was ist so schlimm daran, die ursprüngliche "Autobahn" zu verwenden, und dort wo notwendig ein "goto out" einzubauen? nicht"Gast" schrieb: > Goto wird leider überwiegend verwendet um schlechtes Design zu > kaschieren. Na na na na.... Yalu X. schrieb: > Ein ganz ähnliches Konstrukt ergibt sich, wenn man bspw. in einem > mehrdimensionalen Array ein Element mit einer bestimmten Eigenschaft > suchen möchte. So etwas läuft einem doch öfter über den Weg. Ich sag mal so: Ich weiss das andere das mal brauchten, selber ging mir das noch nie so. Mehrdimensionale Arrays an sich sind etwas mit dem ich sehr selten direkt in Kontakt komme als Java Entwickler, zumnidest in meinem Bereich, das wird wohl auch der Gund sein warum ich ein break label noch nie brauchte.
Gast
#3739167
Michael Reinelt schrieb: > nun kommt die lästige Fehlerbehandlung:tu_was(); > if (!ok) { > cleanup(); > return -E_BE_HAPPY; > } > tu_nochwas(); > if (!ok) { > cleanup(); > return -E_DONT_WORRY; > } > tu_nochwas_drittes(); > if (!ok) { > cleanup(); > return -E_DONT_KNOW; > } > cleanup(); > return 0; Schreib das doch mal mit gotos und zeig mir, dass das lesbarer ist. Michael Reinelt schrieb: > tu_was(); > if(ok) { > tu_nochwas(); > if (ok) { > tu_nochwas_drittes(); > } > } > cleanup(); Mein Gegenvorschlag:
wenn man bei tuwas() und co true für ging und false für ging nicht zurückgibt, ist es ein wenig Übersichtlicher. Allerdings war das Fehlerhandling ja schon immer der Hinkefuß von C. In C++ gibts ja Gottseidank Exceptions für so was. Für die Nörgler: wenn tuwas() 0 zurückgibt, werden die weiteren Funktionen nicht ausgeführt, da das Ergebnis der logischen Verknüpfung fest steht.
Gast
#3739169
Michael Reinelt schrieb: > nicht"Gast" schrieb: >> Goto wird leider überwiegend verwendet um schlechtes Design zu >> kaschieren. > > Na na na na.... Hab nicht geschrieben immer :). Die Beispiele hier im Thread bestätigen mich leider ein wenig.
Gast
#3739171
Gerade im Microcontrollerbereich ist die ROM-Größe oft limitiert. Wenn es dann zu Ketten kommt, wie im Beispiel von Michael beschrieben, sammelt sich durch Fehlerhandling schnell einiger Code an. Wer schon in schwierigen Situation war, am Ende des Projekts zu wenig ROM-Platz zu haben,kennt die Aktionen, die dann gestartet werden um das Projekt zu retten. Strukturierte Programmierung ohne Gotos bleibt dann mit als erstes auf der Strecke, wenn bereits zuvor vernünftig (platzsparend) progranmmiert wurde. Nachteil ist natürlich der höhere Aufwand durch schwierigeres Testen. Wenn allerdings der Compiler (bei uns Keil-C) in einer höheren Optimierungsstufe betrieben wird, werden solche Aktionen teilweise auch vom Compiler eingefügt. Aus meiner Sicht ist an derartigen Anpassungen nichts zu meckern, bei uns in der Firma ist es nur leider so, dass dieser Code unverändert immer wieder übernommen wird, auch wenn es keine Platzprobleme mehr gibt. Hier sollte man sich Gedanken machen, wie dies Optimierungen später einfach lokalisiert und rückgebaut werden können. nicht"Gast" schrieb: > Schreib das doch mal mit gotos und zeig mir, dass das lesbarer ist. fändest du weiter oben schon, aber bitte:
nicht"Gast" schrieb: > if ( ! tuwas() > || ! tuwasanderes() > || ! tuwasdrittes()) > ){ > cleanup(); Einverstanden, geht aber nciht immer: tuwas() und co. sind in meinem Fall nicht als reine Funktionsaufrufe zu verstehen, sondern als (durchaus längere) Codesequenzen, die nicht so einfach einen Return-Wert haben also eher so:
nebenbei: nicht"Gast" schrieb: > if (){ > cleanup(); > return ging_nicht; > } > > cleanup(); > return ging; 2* Cleanup() ge-inlined :-(
Gast
#3739209
Michael Reinelt schrieb: > fändest du weiter oben schon, aber bitte: > tu_was(); > if (!ok) goto out; > tu_nochwas(); > if (!ok) goto out; > du_nochwas_drittes(); > out: > aufraeumen(); Wie wärs damit:
Ich hoffe ich habs richtig geschrieben, im Moment mache ich Pascal, aber man sieht wohl was gemeint ist. Georg
Gast
#3739224
Michael Reinelt schrieb: > .. > if (!a) goto out; > tu_nochwas(); > mach_was_mit_b(); > x=a+b-27; > hallo=x(314)&0xl337; > if (hallo==0) goto out; > du_nochwas_drittes(); > x(); > y(); > z(); > out: > aufraeumen(); Alter, das ist ganz übler Basic-Spaghetti-Code. Besser ist hier eine if else Sequenz.
Gast
#3739237
Michael Reinelt schrieb: > nicht"Gast" schrieb: >> if (){ >> cleanup(); >> return ging_nicht; >> } >> >> cleanup(); >> return ging; > > 2* Cleanup() ge-inlined :-( :) kleine Umänderung
würd ich echt lieber so schreiben, als Gotos einzubauen Michael Reinelt schrieb: > also eher so:bereite_vor(); > initialisiere(); > berechne(); > xxx(); > hole_a() > if (!a) goto out; > tu_nochwas(); > mach_was_mit_b(); > x=a+b-27; > hallo=x(314)&0xl337; > if (hallo==0) goto out; > du_nochwas_drittes(); > x(); > y(); > z(); > out: > aufraeumen(); Massives Refactoring erforderlich :) Leider ist das nicht wirklich ein Code aus dem wahren Leben, sondern zusammengestöpselter wirrer Kram. Dass man da nichts machen kann ist klar. Nachtrag: Das ist einer der besten Beispiele für Spagetticode und eines der schlechtesten Beispiele für guten Code, die ich je gesehen hab :) Thomas schrieb: > Gerade im Microcontrollerbereich ist die ROM-Größe oft limitiert. > Wenn es dann zu Ketten kommt, wie im Beispiel von Michael beschrieben, > sammelt sich durch Fehlerhandling schnell einiger Code an. > > Wer schon in schwierigen Situation war, am Ende des Projekts zu wenig > ROM-Platz zu haben,kennt die Aktionen, die dann gestartet werden um das > Projekt zu retten. Strukturierte Programmierung ohne Gotos bleibt dann > mit als erstes auf der Strecke, wenn bereits zuvor vernünftig > (platzsparend) progranmmiert wurde. > > Nachteil ist natürlich der höhere Aufwand durch schwierigeres Testen. > Wenn allerdings der Compiler (bei uns Keil-C) in einer höheren > Optimierungsstufe betrieben wird, werden solche Aktionen teilweise auch > vom Compiler eingefügt. > > Aus meiner Sicht ist an derartigen Anpassungen nichts zu meckern, bei > uns in der Firma ist es nur leider so, dass dieser Code unverändert > immer wieder übernommen wird, auch wenn es keine Platzprobleme mehr > gibt. Hier sollte man sich Gedanken machen, wie dies Optimierungen > später einfach lokalisiert und rückgebaut werden können. Ja, leider kann ich das so Unterschreiben. Manchmal ist es einfach so, dass man nicht den nächst größeren oder gar einen anderen Controller nehmen kann. Besonders, wenn einem fertigen Gerät immer weitere Features hinzugefügt werden. Da die Hardware zu ändern kann mal schnell teuer werden (FCC, Etsi Neuzulassungen). Das dass aber die Ausnahme sein muss und nicht der Standard, schreibest du ja schon selber. Grüße,
Gast
#3739259
Michael Reinelt schrieb: > 2* Cleanup() ge-inlined :-( Du weist aber schon, dass deine Vorlage deutlich mehr Cleanups beinhaltet Michael Reinelt schrieb: > nun kommt die lästige Fehlerbehandlung:tu_was(); > if (!ok) { > cleanup(); > return -E_BE_HAPPY; > } > tu_nochwas(); > if (!ok) { > cleanup(); > return -E_DONT_WORRY; > } > tu_nochwas_drittes(); > if (!ok) { > cleanup(); > return -E_DONT_KNOW; > } > cleanup(); > return 0; nicht"Gast" schrieb: > Leider ist das nicht wirklich ein > Code aus dem wahren Leben, sondern zusammengestöpselter wirrer Kram. Da hast du recht. ich hatte aber gehofft do könntest etwas besser abstrahieren... nicht ganz so wirr, aber auch aus dem Zusammenhang gerissen: [c] irqe.dest_id = entry->fields.dest_id; irqe.vector = entry->fields.vector; irqe.dest_mode = entry->fields.dest_mode; irqe.trig_mode = entry->fields.trig_mode; irqe.delivery_mode = entry->fields.delivery_mode << 8; irqe.level = 1; irqe.shorthand = 0; if (irqe.trig_mode != IOAPIC_EDGE_TRIG) goto out; spin_lock(&ioapic->lock); __kvm_ioapic_update_eoi(vcpu, ioapic, vector, trigger_mode); spin_unlock(&ioapic->lock); if (!vector) goto out; kvm->arch.vioapic = ioapic; kvm_ioapic_reset(ioapic); kvm_iodevice_init(&ioapic->dev, &ioapic_mmio_ops); ioapic->kvm = kvm; mutex_lock(&kvm->slots_lock); ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, pic->base_address, IOAPIC_MEM_LENGTH, &ioapic->dev); mutex_unlock(&kvm->slots_lock); if (ret < 0) goto out; [c] Was ich sagen will: Du hast eine nicht ganz so kurze Sequenz fon Operationen (Zuweisungen, Funktionsaufrufe, berechnungen) die im normalfall einfach linear von vorne bis hinten durchlaufen werden. Die Blöcke kannst du auch nciht wie du oben vorgeschlagen hast, mit || zusammenhängen. An bestimmten stellen kann was schief gehen (ist aber die Ausnahme), und da bietet sich ein goto als "Ausstieg" an. Für mich (und ich bin hier nicht alleine) viel besser lesbar als tiefe if() verschachtelungen. nicht"Gast" schrieb: > Du weist aber schon, dass deine Vorlage deutlich mehr Cleanups > beinhaltet Und wenn du mein kommentar dazu gelesen hättest, wüsstest du dass ich das absichtlich gemacht habe, um zu zeigen welche nachteile diese Konstellation hat :-(
Gast
#3739318
Michael Reinelt schrieb: > Und wenn du mein kommentar dazu gelesen hättest, wüsstest du dass ich > das absichtlich gemacht habe, um zu zeigen welche nachteile diese > Konstellation hat :-( ja, da hast du recht. Bei der ersten Antwort hatte ich es noch gelesen. Bei der zweiten .. na ja, shame on me :) Michael Reinelt schrieb: > Da hast du recht. ich hatte aber gehofft do könntest etwas besser > abstrahieren... Also DAS zu abstrahieren ist echt ne Herausforderung. Da scheitern sicher auch Leute mit mehr Grips als ich dann. Dein Code aus dem zweiten Post ist auch nicht der Renner. Du scheinst zu viele Sachen in deine Funktion zu stecken. Ohne den Rest zu kennen: Teil das Ganze in kleinere Blöcke auf und du wirst sehen, dass das Ergebnis deutlich lesbarer als die Gotos sind. Bsp: statt dem ersten Block
Wenn du mehrere trigger modes hast, pack das lieber in ein switch, dass dann Funktionen aufruft. Das ist um Welten übersichtlicher, als das, was du gepostet hast. Grüße, Ich möchte hier noch eine andere Möglichkeit zur Diskussion stellen, Initialisierungssequenzen mit Ausstiegspunkten ohne explizite Gotos und verschachtelte Ifs in C zu realisieren. In folgendem Beispiel wird angenommen, dass die drei Init-Funktionen im Fehlerfall einen von 0 verschiedenen Fehlercode liefern. Jeder Fail landet automatisch an der dem BLOCK_END folgenden Anweisung.
Mal an die Theoretiker und Praktiker hier: Der diesjährige ICFPC startet in ein paar Minuten. Viel Spaß mit und ohne goto :) http://icfpcontest.org/
Gast
#3739408
Also das for-"Problem" lässt sich auf mehre Weisen lösen: 1. jede Schleife kann mehrere Abbruchbedingungen haben:
Wenn man nach dem Abbruch wieder vor die Schleifen springen muss:
1. Ja, manchmal habe ich das Gefühl, nur 20 Menschen auf diesem Planeten
kennen noch eine do-while-Schleife...
2. Bitte im echten Code jede Schleife mit {} versehen, sonst sieht man
bei solchem Code auch ohne goto nicht mehr durch.
Da ich persönlich for-Schleifen mit mehreren Bedienungen nicht mag, da
man damit einfach nicht rechnet, würde ich die drei for-Schleifen in
while Schleifen verwandeln
Um nochmal zum Originalthema zurückzukommen. Ich kenne auch sinnvolle goto's. Ein Beispiel ist eine Art try catch nachzubauen:
Schönes Wochenende
Gast
#3739410
Ich war whol richtig langsam beim beantworten. Yalu X meint hier wohl das gleiche wie ich. emp schrieb:
>
> > Schönes Wochenende Die Variante mit den For-Schleifen finde ich toll, das hab ich so noch nie gesehen. Was das letzte Beispiel angeht: Da kannst du auch gleich eine Funktion MyErrorHandler(ERR_TYPE) aufrufen und hast sogar eine Unterscheidung dabei. Mit nahezu gleichem Codeaufwand wie beim GOTO. Daniel Yalu X. schrieb: > #define BLOCK_BEGIN do { > #define BLOCK_END } while(0) > #define FAIL_IF(x) if(x) break Ich bin versucht zu sagen "real programmers don't use Pascal", aber ich verkneifs mir mal ;-) Grundsätzlich natürlich eine Möglichkeit, nur: warum so viel Aufwand, nur um ein goto zu tarnen? nicht"Gast" schrieb: > Dein Code aus dem zweiten Post ist auch nicht der Renner. ist nicht mein Code :-) > Du scheinst zu viele Sachen in deine Funktion zu stecken. Ohne den Rest > zu kennen: Teil das Ganze in kleinere Blöcke auf und du wirst sehen, > dass das Ergebnis deutlich lesbarer als die Gotos sind. nein, werde ich nicht. und das ist nicht mal unbedingt meine Meinung. Der Code wurde recht wahllos aus den aktuellen Linux-Sourcen rauskopiert (irgendwas im KVM-Bereich) Ohne jetzt einen Glaubenskrieg anzetteln zu wollen: Ich hab in meinem Leben sehr viel Code gelesen, viel guten Code, ein paar echte "perlen", und leider bei weitem zu viel schlechten Code. Für mich zählt der Linux-Kernel-Source auf jeden Fall zu den positiven Beispielen. Der Code ist gut, effizient, leistungsfähig, und durch viele Hände gegangen, und wurde von sehr vielen Augen gelesen. Goto ist dort alles andere als verboten, wird aber mit Bedacht eingesetzt. Du kannst ja mal versuchen, dort zu predigen, wie du das alles viel besser machen würdest. Gib mir aber bitte vorher Bescheid, den Thread möchte ich nicht verpassen :-) Ums nochmal auf den Punkt zu bringen: Goto hat absolut seine Berechtigung in gewissen Fällen: kritischer Code, kleiner (Cache-)Footprint, Rücksicht auf die Pipeline sind ein paar davon. Ein guter Programmierer kennt das, weiß das zu schätzen und kann einschätzen wann ein goto angebracht ist und wann nicht. Das reflexartige "goto ist böse" deutet nur auf eins hin: Die Aussage kommt nicht von einem guten, erfahrenen Programmierer.
Gast
#3739450
Ich schicke den Link nochmal. Hat offensichtlich keiner gelesen. Wer mag, der kann sich auch die ganze Diskussion durchlesen, aber der verlinkte Post reicht eigentlich. http://programmers.stackexchange.com/questions/154974/is-this-a-decent-use-case-for-goto-in-c/154980#154980 Now stop this :)
Gast
#3739454
>Da ich persönlich for-Schleifen mit mehreren Bedienungen nicht mag
Wie sieht so eine Bedienung einer for-Schleife aus? Start-Stopp-Abbruch?
;-)
Klaus Kaiser schrieb: > http://programmers.stackexchange.com/questions/154974/is-this-a-decent-use-case-for-goto-in-c/154980#154980 Schön, danke! Trifft genau das was ich versuche zu vermitteln. <duckundwegrenn> nur müssten das die Mädels hier verstehen wollen... </duckundwegrenn>
Gast
#3739717
nicht"Gast" schrieb: > Sollte der Compiler nicht bei dir auch meckern? Nein. Er erkennt nämlich direkt zuvor den unbedingten Sprung und weiß dann, daß das Ende unerreichbar ist. Ich hab aber aus Klaus Kaisers Link ne Sache, die mir durchaus sinnvoll erscheint, obwohl sie etwas störrisch aussieht: ... if (Procedure_A()==fail) goto undo_A; if (Procedure_B()==fail) goto undo_B; if (Procedure_C()==fail) goto undo_C; ... return OK; undo_C: Undo_Procedure_C(); undo_B: Undo_Procedure_B(); undo_A: Undo_Procedure_A(); return Failed; De Knackpunkt ist hierbei das korrekte Zurückrollen von den Dingen, die bereits angerichtet sind. Man versuche das mal stringenter auszudrücken. W.S.
Gast
#3739726
>Ums nochmal auf den Punkt zu bringen:
oder anders gesagt, reine Geschacksache, was 'besser' lesbar ist.
Und einem Compiler sollte es sowiso egal sein, welche 'switches' er
vorfindet.
Goto in ASM stiftet nur Verwirrung, weil es dort sinngemäss JMP heissen
müsste.
MCUA schrieb: > oder anders gesagt, reine Geschacksache, was 'besser' lesbar ist. W.S. schrieb: > Man versuche das mal stringenter auszudrücken. Jein ich behaupte, goto macht den Code oft schlechter lesbar, (oft für "eingeweihte" durchaus auch besser) Es geht aber nicht nur um die Lesbarkeit, sondern meist darum, dem Compiler zu erlauben, kompakten, effizienten und damit optimalen Code zu erzeugen. In manchen Bereichen (OS Kernel, embedded mit "engen" bedingungen) ist das notwendig. ich weiss schon, "... the root of all evil", aber das obige Konstrukt von W.S. ist es wert, es sich anzugewöhnen. Es ist straight, sauber, optimal, schön. (Leider wird man damit in der Ausbildung/Uni vermutlich Probleme bekommen. Liegt aber IMHO daran, dass Ausbildner selten viel Programmiererfahrung haben, eher Theoretiker sind. und in der Theorie gibts ja keinen Unterschied zwischen Theorie und Praxis, aber in der Praxis sehr wohl) MCUA schrieb: > Goto in ASM stiftet nur Verwirrung, weil es dort sinngemäss JMP heissen > müsste Wieso, es ist doch egal ob man zur Zieladresse hingeht oder springt... Wenn sich der Hersteller für eines der beiden oder vllt. noch ein anderes Mnemonic entschieden hat dann ist es ganz eindeutig was GOTO/JMP für diesen Prozessortyp bedeutet.
Gast
#3739769
Yalu X. schrieb: > Ich möchte hier noch eine andere Möglichkeit zur Diskussion stellen Von Sprache neu definieren mittels Präprozessor halt ich gar nichts. Warum nicht dein Konstrukt so lassen, aber mit do, if und break.
Gast
#3739780
>Es geht aber nicht nur um die Lesbarkeit, sondern meist darum, dem >Compiler zu erlauben, kompakten, effizienten und damit optimalen Code zu >erzeugen. Den Compiler hat das nicht zu jucken. Ansonst bleibt es dabei, es ist Geschmacksache (sagt der Andere und beisst in die Seife). >Wieso, es ist doch egal ob man zur Zieladresse hingeht oder springt... natürlich ist es wurscht, aber kein Mensch (ausser die von PIC) verwenden für JMP Goto in ASM. Warum der Quatsch? (doch nicht um mit 'goto' ein Hochsprachenkonstrukt im ASM zu assoziiren) (allerd. ist bei PIC (aus Urzeiten) syntakt. vieles anders). MCUA schrieb: > Den Compiler hat das nicht zu jucken. Leider sind wir noch nicht im Jahr 2525. Heute macht der Compiler noch was du tippst, und nicht was du willst.
Gast
#3739885
Michael Reinelt schrieb: > Der Code wurde recht wahllos aus den aktuellen Linux-Sourcen rauskopiert > (irgendwas im KVM-Bereich) Da hast du mich aber erwischt. Trozdem bleibt das Stück Code scheiße. Es fehlt einfach der Kontext um das beurteilen zu können. Wenn du die gesamte Funktion gepostet hättest, würde das sicher anders aussehen, aber so bleibt es unzusammenhängendes Geschwurbel. nicht"Gast" schrieb: > Trozdem bleibt das Stück Code scheiße. Watch your language! > Es > fehlt einfach der Kontext um das beurteilen zu können. Wenn du die > gesamte Funktion gepostet hättest, würde das sicher anders aussehen, > aber so bleibt es unzusammenhängendes Geschwurbel. www.kernel.org Ich sprech dir jetzt einfach mal die Kompetenz ab, das zu beurteilen. Vermutlich ist es besser du schreibst weiter deine tic-tac-toe programme ohne goto's ... <sorry> MCUA schrieb: > natürlich ist es wurscht, aber kein Mensch (ausser die von PIC) > verwenden für JMP Goto in ASM. Warum der Quatsch? (doch nicht um mit > 'goto' ein Hochsprachenkonstrukt im ASM zu assoziiren) (allerd. ist bei > PIC (aus Urzeiten) syntakt. vieles anders). Quatsch ist, sich darüber aufzuregen. Ich glaube nicht, dass alle Hersteller verpflichtet sind, die Nomenklatur von Intel zu übernehmen.
Gast
#3740016
Walter Tarpan schrieb: > if (status!=0) > goto error; > > return status; // = 0 > > error: > I2C_reset(EEPROM_I2C_DEVICE); > return status; Ein hervorragendes Beispiel für die verwendung eines Goto. Könntest du aber noch deutlich verbessern: goto unten oben: goto abfrage fallja: goto entwederoderdochnicht abfrage: goto fallja alsodochdoch: if (status!=0) goto error; goto noerror error: I2C_reset(EEPROM_I2C_DEVICE); return status; noerror: return status; // = 0 entwederoderdochnicht: goto alsodochdoch unten: goto oben BTW genau soetwas ist der Grund warum es für Anfänger verboten ist goto zu verwenden. Weil dann so ein Mist entsteht und sie es sich angewöhnen, ... oder es sogar noch als sinvolles Beispiel posten. Nirgendwo war es überflüssiger als in diesem Beispiel.
Gast
#3740115
Sollte man nicht alle anderen Statements, mit denen man bei genügend Anstrengung Schindluder treiben kann, auch verteufeln. Immer nur auf das arme GOTO, wie gemein. Und ist nicht das Beispiel
auch ein simuliertes GOTO. Indirekt, über die zuvor auf dem Stack abgelegte Ziel-Adresse. Schreibt einer, der die Wahl nicht hat, denn die Sprache, in der er seit 25 Jahren seine Brötchen programmiert, ist GOTG frei. Freizeit Code auf'm AVR in C hat aber manchmal ein goto, damit jede Version des Compilers sich beim Optimieren an seine Vorgaben hält. Die Welt ist eben nicht Schwarz/Weis, sondern hell-/dunkel-grau. @Karl und @Yalu Danke für die Erläuterungen. Jeder Assembler hat ein GOTO und die diversen mehrfachen return, break etc. C-Konstrukte können nur mit GOTO/JUMP in ASM umgesetzt werden. Jaja, Ein Hochsprachen GOTO ist halt irgendwie gefühlt anders als ein ASM GOTO. Yalu X. schrieb: >
Das ist genau der Fall, wo ich die define so abändern würde:
Ganz einfach aus dem Grund, weil es dem Wesen nach keine Schleife ist. Aber lieber schreibe ich offen und ehrlich das goto hin. Zwergenball schrieb: > BloedeFrage schrieb: >> Sämtliche Leute die mir bisher programmieren beigebracht haben > > Wie viele haben dir das programmieren beigebracht? Welche > Programmiersprachen hast du dabei erlernt? Haben diese Leute die > Forderung - goto nicht zu verwenden - begründet? Wie wurde die Forderung > begründet? Wie alt bist du? Welchen Schulabschluss hast du? Hast du > einen Hochschulabschluss? Wenn ja, welchen Anschluss hast? ... und wieso bist du so neugierig? Deine Fragen haben doch nichts mit der eigentlichen Frage zu tun. W.S. schrieb: > Ein simples > Beispiel ist die Grundschleife bei Mikrocontrollern: > int main (void) > { initialisiere(); > immerzu: > machedies(); > machedas(); > machenochwas(); > goto immerzu; > } > Wenn man das mit einem while(1) formuliert, dann meckern manche > Compiler, daß main ja gar kein Ergebnis zurückgibt - zu Recht (im > Prinzip). Also findet man bei solchen Strategen nach der Endlosschleife > noch ein return 0 oder so, um den schieren Formalismus zu befriedigen. Compiler-Meckern hin oder her, das hier ist dem Wesen nach eine Endlos-Schleife und ein while(1) bringt genau das zum Ausdruck. Hier finde ich das goto deshalb fehl am Platz. foo schrieb: > Yalu X. schrieb: >> Ich möchte hier noch eine andere Möglichkeit zur Diskussion stellen > > Von Sprache neu definieren mittels Präprozessor halt ich gar nichts. > Warum nicht dein Konstrukt so lassen, aber mit do, if und break. Weil das do-while eine Pseudoschleife ist und deswegen Verwirrung stiften könnte. Aber ich stimme dir trotzdem zu: Solche Makros, die etwas anderes definieren als Konstanten oder funktionsähnliche Dinge, mag ich eigentlich auch nicht. Konrad S. schrieb: > Das ist genau der Fall, wo ich die define so abändern würde: > > #define BLOCK_BEGIN > #define BLOCK_END block_end: > #define FAIL_IF(x) if(x) goto block_end > > Ganz einfach aus dem Grund, weil es dem Wesen nach keine Schleife ist. > Aber lieber schreibe ich offen und ehrlich das goto hin. Die do-while-Schleife habe ich aus drei Gründen verwendet: 1. Man braucht kein Goto-Label. Somit können auch mehrere BLOCK_BEGIN- BLOCK_END-Konstrukte nacheinander in einer Funktion verwendet werden, ohne dass es Konflikte mit Labels gleichen Namens gibt. 2. Mehrere BLOCK_BEGIN-BLOCK_END-Konstrukte nacheinander werden selten benötigt. Manchmal möchte man sie aber verschachteln können, bspw. in solchen Fällen: Klaus Kaiser schrieb: http://programmers.stackexchange.com/questions/154974/is-this-a-decent-use-case-for-goto-in-c/154980#154980 Dank der verwendeten Pseudoschleife geht das problemlos, und der Compiler kontrolliert dabei die korrekte Verschachtelung. 3. Die Definition von BLOCK_BEGIN und BLOCK_END als Schleife verhindert, dass sie unsinnig platziert werden, bspw. in unterschiedlichen Blöcken, in der falschen Reihenfolge (BLOCK_END vor dem BLOCK_BEGIN) oder in anderen spaghettiverdächtigen Anordnungen. Deren Verwendung wird damit deutlich eingeschränkt und erlaubt es dem Compiler, einige Fehler zu erkennen, die bei der Verwendung von Goto unentdeckt blieben. Zugegebenermaßen benutze ich diese Makros selber auch nicht, da auch die sorgfältige Verwendung von Gotos normalerweise nicht zu Problemen führt. Ich habe sie mir nur für solche Leute ausgedacht, denen die direkte Verwendung von Gotos in zur Fehlerbehandlung zweifelhaft erscheint und die – durchaus nachvollziehbar – einen Break dem Goto vorziehen. Yalu X. schrieb: > Zugegebenermaßen benutze ich diese Makros selber auch nicht, da auch die > sorgfältige Verwendung von Gotos normalerweise nicht zu Problemen führt. Eben! Und wer kein goto mag und ohne auskommt, der darf auch glücklich werden. ;-) W.S. schrieb: > Ich hab aber aus Klaus Kaisers Link ne Sache, die mir durchaus sinnvoll > erscheint, obwohl sie etwas störrisch aussieht: > > ... > if (Procedure_A()==fail) goto undo_A; > if (Procedure_B()==fail) goto undo_B; > if (Procedure_C()==fail) goto undo_C; > ... > return OK; > > undo_C: > Undo_Procedure_C(); > undo_B: > Undo_Procedure_B(); > undo_A: > Undo_Procedure_A(); > return Failed; > > De Knackpunkt ist hierbei das korrekte Zurückrollen von den Dingen, die > bereits angerichtet sind. Man versuche das mal stringenter auszudrücken.
Gast
#3740472
Sanfte Grüße, Michael Reinelt schrieb: > nicht"Gast" schrieb: >> Trozdem bleibt das Stück Code scheiße. > Watch your language! Vielen Dank für die Korrektur meiner inneren Einstellung. :) Ich hab mir mal deine Vorwürfe zu Herzen genommen und mir die aktuellen Sourcen heruntergeladen. Ich bin mir nicht sicher, ob ich die richtige Funktion gefunden hab, deswegen poste ich sie mal hier. Allerdings taucht in ihr das einzige mal im gesamten Source das struct irqe auf.
Wenn ich die Richtige erwischt hab, scheint da wohl doch einer ein Refactoring betrieben zu haben und hat die Gotos rausgeschmissen. In anderen Funktionen in dieser Datei (ioapic.c) gibs natürlich auch noch Gotos. Aber es scheint schon einen gewissen Trend zu geben. Deine Beurteilung über meine Qualifikation tangiert mich damit auch nicht mehr wirklich. An dieser Stelle sei gesagt: Der absolut überwiegende Teil der Kernelentwickler lässt mich mit Sicherheit wie ein Baby aussehen. Daran gibts kein Zweifel. **** Ich hab übrigens in einem anderen Post schon geschrieben, dass es durchaus Situation gibt (ja, hatte ich auch schon selber), in denen Goto seinen Sinn hat. Ich glaub, ich muss mal meine Einstellung klarstellen :) Bei meinen Coding geht es immer um: - Lesbarkeit - Wartbarkeit - Wiederverwendbarkeit Die Fehlerfreiheit überragt natürlich alles ^^. Ich behaupte auch an der Stelle nicht, dass ich so gut bin, dass ich es immer hinbekomme. Ich hab schon nach 2 Wochen schon mal ein halbes Programm umstricken müssen, weil ich es nicht mehr verstanden habe. Da ich performance unkritische Sachen entwickle, steht das auch gar nicht auf meiner Agenda. Manchmal musste ich allerdings auch schon in einige Richtungen optimieren, weil zum Beispiel auf einmal der Speicherverbrauch epxlodiert ist. Die Beispiele mit Goto hier im Thread bedeuten für mich bisher immer eine schlechtere Lesbarkeit weil sie unnötig einen Bruch im Code darstellen. Geschweifte Klammern zeigen immer schön Start und Ende eines Scopes an. Sprungziele von gotos können überall sein und man muss sie erst suchen. Was ich meine:
warum kann ich meine Funktion nicht so stricken, dass Undo_Procedure_C() direkt ausgeführt wird wo's fehlschlägt? Dann seh ich sofort, was passiert. So muss ich erst zum Goto Ziel (vielleicht noch scollen). btw. ist das wirklich gut, dass im Fehlerfall der Undo Code von allen drei Methoden ausgeführt wird? An der Stelle nicht vergessen. Goto kann vorkommen. Ist ja nicht umsonst in den meisten Sprachen integriert. Der Ottonormal Durchschnittsprogrammierer tut sich jedoch in dem meisten Fällen eher schlecht damit und sollte seinen Code lieber so strukturieren, dass er es nicht braucht. Damit meine ich nicht die kleinen Beispiele hier, sondern das fängt schon eine Ebene weite höher im Funktionsaufbau an. Überwiegend kommt dabei besser lesbarer Code raus. Wenn die Lesbarkeit aus zwingenden Gründen leiden muss um sein Ziel zu erreichenm, dann soll es so sein. Vermeiden sollte man das aber in standard Situationen. Das auch Profis mit Goto manchmal nicht umgehen können zeigt ja Apple sehr schön :) https://gotofail.com/faq.html nicht"Gast" schrieb: > Wenn ich die Richtige erwischt hab, scheint da wohl doch einer ein > Refactoring betrieben zu haben und hat die Gotos rausgeschmissen. Es ist der falsche Code. Der von mir zitierte war irgendwo aus dem Bereich kvm. und er war aktuell (2.6.15) Aber - bevor du weitersuchst: der tatsächliche Code tut absolut nichts zur sache! ich wollte damit nur illustrieren, das es nicht immer so einfach ist wie in den hier gebrachten Beispielen, proc_a() ist eben nicht nur eine zeile, sondern das können auch viele sein. (Und auf deinen Vorposter geh ich deshalb erst gar nicht mehr ein - ich kapituliere) nicht"Gast" schrieb: > Deine Beurteilung über meine Qualifikation tangiert mich damit auch > nicht mehr wirklich. War auch weder ernst noch persönlich gemeint - lassen wirs gut sein? nicht"Gast" schrieb: > Die Beispiele mit Goto hier im Thread bedeuten für mich bisher immer > eine schlechtere Lesbarkeit weil sie unnötig einen Bruch im Code > darstellen. Geschweifte Klammern zeigen immer schön Start und Ende eines > Scopes an. > Sprungziele von gotos können überall sein und man muss sie erst suchen. Siehst du, ich seh's genau gegenteilig: Das Schöne am Goto ist, dass das Sprungziel da steht, und ich schnell danach suchen kann; während ich beim break erst (mühsam) das Ende des Scopes suchen muss. und von der anderen seite her: wenn ich ein Label sehe, weiss ich dass es (vermutlich) angesprungen wird - was ich bei einer geschlossenen geschwungenen Klammer erstmal nicht erkennen kann. nicht"Gast" schrieb: > warum kann ich meine Funktion nicht so stricken, dass Undo_Procedure_C() > direkt ausgeführt wird wo's fehlschlägt? Nochmal: weil ich Code nicht duplizieren will. und selbst wenn ich so klug bin, undo_procedure_c() in eine Funktion auszulagern (was in den wenigsten Fällen Sinn macht, weil ich gefühlte tausend parameter übergeben müsste) kommt der Compiler (mein Freund und Helfer) und dupliziert den Code, weil er den aufruf inline macht. Das will ich nicht, weil es meinen Cache-Footprint unnötig erhöht. Ich bin ja auch keineswegs der Meinung, man sollte goto verwenden. keinesfalls! ich selbst verwende es eher selten. Was ich aber nicht ausstehen kann, ist das "goto ist böse", und das sofortige "Der Code ist scheisse, weil ein goto drinnen ist". Das zeigt nur eines - derjenige hat es nicht verstanden. Und was ich beängstigend finde - dass obiges offensichtlich gelehrt wird. Und wie sich hier in diesem Thread wieder zeigt - so viele fühlen sich berufen, zu erklären wie man's besser machen sollte. Und keiner versteht, dass er (in bestimmten Fällen) einfach falsch liegt. Keiner liest Klaus Kaisers Link, und wenn er gelesen wird, wird er nicht verstanden. Traurige Programmierer-Welt :-(
Gast
#3740536
Michael Reinelt schrieb: > War auch weder ernst noch persönlich gemeint - lassen wirs gut sein? Gerne (Handshake) Im Grunde reden wir ja mit fast der gleichen Meinung aneinander vorbei :) Eigentlich finde ich es ganz gut, dass es nicht gelehrt wird. Anfänger werden durch so was zu schlechten Code verleitet (Ich hoffe das bestreitest du nicht :). Wenn man wirklich mal an den Punkt kommt, an dem man es nicht vermeiden kann, ist man meistens auch so weit, dass man es vernünftig benutzen kann. Übrigens ein 'grep -Ro "goto" | wc -l' über den aktuellen Source (3.15.6) ergibt die Zahl 117157. Das ist mal krass. Grüße,
Gast
#3740652
Inzwischen scheint der TO vom Thread plattgewalzt worden zu sein.
Um aber nochmal auf die Ursprungsfrage nachdem "warum" zu kommen,
sind mir folgende mehr oder weniger historische Begründungen
bekannt (gemacht) worden:
1. Das menschliche Gehirn verarbeitet tendenziell Strukturen
besser als zeitliche Abfolgen. Ein Programm, das nur aus
If/While/Abfolgen und Prozeduraufrufen besteht, ist quasi
statisch ("diese Schleife schneidet die Verzeichnisse von den
Pfadnamen ab, diese Prozedur..."). Den Gegenpol dazu bildet
ein rein goto-basiertes 'lineares' Programm, dessen zeitlicher
Ablauf nachvollzogen werden muss, um es zu verstehen.
Beispiel aus dem Alltag wäre ein Tankwart, der einem Touristen
auf der Karte zeigt: "Sie sind hier und wollen nach da" vs.
ohne Karte: "Sie fahren die X-Strasse entlang, bei der dritten
Ampel rechts, dann bis zum Y-Ring, folgen dem bis zu ..."
(zehn weitere Stationen - Tourist hat längst den Faden
verloren).
2. Das goto-Verbot wurde aufgestellt, als die Software-Krise zum
erstenmal bewusst wahrgenommen wurde. Da kam die Forderung auf,
Programme sollten so einfach und modularisiert wie möglich
sein. Goto galt als das Mittel, um Programmteile zu einem
undurchdringlichen Monolithen zu verbinden ("big ball of mud").
3. Parallel zur Software-Krise gab es eine Hype-Phase für die
'formale Verifikation', also den Wunsch, Korrektheit von
Software mathematisch zu beweisen. Die strukturierte
Programmierung kam der vielfach verwendeten Hoare-Logik und
dem Floyd-Invariantenverfahren sehr entgegen, während goto
die Kalküle schnell an ihre Grenzen brachte - umso mehr, als
man damals noch im wesentlichen mit Zettel und Stift bewies.
Dieses Argument sticht heute kaum noch, vor allem weil die
Verifikationstechnik sich als i.a. wirtschaftlich unrentabel
herausstellte.
nicht"Gast" schrieb: > Eigentlich finde ich es ganz gut, dass es nicht gelehrt wird. Mißverständnis: ich bin nicht dafür dass goto gelehrt wird, aber ich verwehre mich gegen die Lehre "goto => böse" > Anfänger > werden durch so was zu schlechten Code verleitet (Ich hoffe das > bestreitest du nicht :). Nö :-) nicht"Gast" schrieb: > Übrigens ein 'grep -Ro "goto" | wc -l' über den aktuellen Source > (3.15.6) ergibt die Zahl 117157. Das ist mal krass. Du findest das krass. Ich nicht ;-)
Gast
#3744363
>> natürlich ist es wurscht, aber kein Mensch (ausser die von PIC) >> verwenden für JMP Goto in ASM. Warum der Quatsch? (doch nicht um mit >> 'goto' ein Hochsprachenkonstrukt im ASM zu assoziiren) (allerd. ist bei >> PIC (aus Urzeiten) syntakt. vieles anders). >Quatsch ist, sich darüber aufzuregen. Ich glaube nicht, dass alle >Hersteller verpflichtet sind, die Nomenklatur von Intel zu übernehmen. Aber warum (nur bei PICs) Gotu in ASM , wo es doch (verteufelterweise) in Hochsprachen benutzt wird? In C macht goto Sinn, weil es oft keine andere vernünftige Möglichkeit gibt, Resourcen wieder freizugeben. Deshalb ist das auch im Linux-Kernel so viel vorhanden und dort auch ok. In C++ möchte ich aber mal ein Beispiel sehen, wo es sinnvoll ist goto zu benutzen. Die letzten fünf gotos die ich in C++-Code gefunden habe konnte man durch ein kürzeres und übersichtlicheres nicht-goto-Konstrukt ersetzen. MCUA schrieb: > Aber warum (nur bei PICs) Gotu in ASM Der PIC Assembler kennt den "Gotu" Befehl nicht mal...
Gast
#3752862
Ich verwende auch goto zum deinitialisieren meiner Funktionen. Hab bis jetzt noch keine elegantere Lösung gefunden. Siehe auch: Beitrag "C: Fehlerbehandlung und -weiterleitung" Antwort schreibenBitte melde dich an, um einen Beitrag zu schreiben. |
Anzeige
|