Hallo zusammen,
Ich habe einen Programmcode für einen Tiny 84, den ich persönlich
unleserlich finde. Daraufhin habe ich diesen Modularisiert und gemerkt
das der Flash Speicher mehr in anspruch genommen wurde und die Zeiten
nicht mehr passten. Eine andere möglichkeit die mir einfällt ist, den
Programmcode mittels #define in unterschiedliche Header zu
Modulariseren, dabei dürfte ich dann ja keinen Verlust beim
Flashspeicher, etc. haben. Nun meine Frage, ist das nutzen von
Präprozessordirektiven zum Modularisieren (Lesbarer Code) schlecht, in
hinblick darauf das eventuell irgendwann andere Kollegen mit diesem Code
arbeiten?
@ Sven (Gast)
>unleserlich finde. Daraufhin habe ich diesen Modularisiert und gemerkt>das der Flash Speicher mehr in anspruch genommen wurde und die Zeiten>nicht mehr passten.
Dann hast du falsch modularisiert.
>Eine andere möglichkeit die mir einfällt ist, den>Programmcode mittels #define in unterschiedliche Header zu>Modulariseren, dabei dürfte ich dann ja keinen Verlust beim>Flashspeicher, etc. haben. Nun meine Frage, ist das nutzen von>Präprozessordirektiven zum Modularisieren (Lesbarer Code) schlecht,
Kommt drauf an. Man kann alles übertreiben und vermurksen. Man sollte
keine zu komplexen Konstrukte per #define machen, auch mit #define
Macros sollte man eher sparsam umgehen.
Sven schrieb:> Daraufhin habe ich diesen Modularisiert und gemerkt das der Flash> Speicher mehr in anspruch genommen wurde und die Zeiten nicht mehr> passten.
Das wird dann an dem liegen, was Du "modularisieren" nennst. Was genau
stellst Du Dir darunter vor? Kannst Du das anhand eines Beispiels
illustrieren?
> Eine andere möglichkeit die mir einfällt ist, den Programmcode mittels> #define in unterschiedliche Header zu Modulariseren,
Was aber magst Du damit meinen?
> Nun meine Frage, ist das nutzen von Präprozessordirektiven zum> Modularisieren (Lesbarer Code) schlecht, in hinblick darauf das> eventuell irgendwann andere Kollegen mit diesem Code arbeiten?
Da bereits das kaum zu verstehen ist:
Versuch mal anhand eines Beispiels zu zeigen, was Du Dir unter
"Präprozessordirektiven zum Modularisieren" vorstellst.
Ich verstehe nicht was du mit "mittels #define in unterschiedliche
Header zu
Modulariseren" meinst.
Modularisieren soll man ja nicht zum Selbstzweck, sondern man sollte
einfach die Aufgaben eines Projekts sinnvoll in Module einteilen.
Wenn der Speicherplatz nicht kritisch ist, sollte man grundsätzlich ein
lesbares Programm einem speicherplatzoptimiertem Programm vorziehen.
Sven schrieb:> Ich habe einen Programmcode für einen Tiny 84, den ich persönlich> unleserlich finde. Daraufhin habe ich diesen Modularisiert und gemerkt> das der Flash Speicher mehr in anspruch genommen wurde und die Zeiten> nicht mehr passten.
Falsche Ansatz,
der Code braucht kein Facelift, der Code braucht ne Dokumentation.
Du kannst den GCC zwingen, Funktionen zu inlinen. Ich hab mir dafür ein
Macro geschrieben:
1
// Always Inline
2
#define AIL(x) static inline x __attribute__ ((always_inline)); static inline x
3
#define INLINE(x) AIL(x)
Nur einmal aufgerufene Funktionen sollte er aber automatisch inlinen.
Schau mal ins Assemblerlisting, welcher Code teuer ist.
Persönlich habe ich bei Modularisierung eher den Effekt, daß der Code
kleiner wird.
Peter schrieb:> Ich verstehe nicht was du mit "mittels #define in unterschiedliche> Header zu> Modulariseren" meinst.
Ich auch nicht, könnte mir aber vorstellen, dass er das mit #include
verwechselt. (?)
Falls ja, könnte er meinen, sein ehemals großes Source-File in kleine
Files zu zerlegen und diese dann in einem zu includieren.
Als unwissender Student habe ich das zumindest eine Zeit lang so
gemacht, bis mir klar wurde, wie man es richtig macht mit dem
Compilieren und Zusammenlinken unterschiedlicher Sourcen.
bsp:
main()
{
int a,b, c;
a =2;
b=3;
c = a + b;
}
=>
main()
{
int c;
c = summe(a,b);
}
int summe(int a, int b)
{
return a + b;
}
=>
main()
{
#SUMME
}
In der Header
#SUMME int a,b, c;\
a =2;\
b=3;\
c = a + b;
Sven schrieb:> und die Zeiten> nicht mehr passten.
Das darf eigentlich nicht passieren. Zeiten macht man mit Timern oder
_delay_us().
Wenn sie nicht mehr passen, deutet das auf hohen Overhead hin, z.B.
falscher Optimierungslevel, verschwenderische Verwendung von Pointern
auf Pointern, unnötig große Datenformate.
Wenn ich doch eine Methode aufrufe werden doch Daten auf den Stack
geschrieben und eine Sprunganweisung ausgeführt. Wenn ich dagegen den
Code Sequentiell ausführe, dann benutzt er keine Sprunganweisung und
muss auch nicht notwendigerweise Daten auf dme Stack schrieben und
sichern.
Sven schrieb:> =>> main()> {> #SUMME> }
Das ist unleserlich, unwartbar und unübersichtlich, also exakt das
Gegenteil, was Du mit Deiner Modularisierung erreichen willst.
Vielleicht zeigst du uns einfach mal deinen Code (vor und nach deiner
"Modularisierung")
Peter D. schrieb:> verschwenderische Verwendung von Pointern> auf Pointern
Daran hab ich grad ganz ganz große zweifel ;-)
Sven schrieb:> =>> main()> {> #SUMME> }>> In der Header> #SUMME int a,b, c;\> a =2;\> b=3;\> c = a + b;
Mit anderen Worten, Du ruinierst gerade die Codebasis. Der nachfolgende
Programmierer, der hoffentlich mehr Erfahrung hat, kann den Müll dann
nur noch wegwerfen.
@ Sven (Gast)
>Wenn ich doch eine Methode aufrufe werden doch Daten auf den Stack
Du hast gar keine Methoden sonder schnöde Funktionen, denn das ist
garantiert "nur" C und kein C++.
>geschrieben und eine Sprunganweisung ausgeführt. Wenn ich dagegen den>Code Sequentiell ausführe, dann benutzt er keine Sprunganweisung und>muss auch nicht notwendigerweise Daten auf dme Stack schrieben und>sichern.
Richtig. Solche Sachen darf man natürlich nicht in zeitkritische
Sequenzen einbauen.
Sven schrieb:> main()> {> int a,b, c;> a =2;> b=3;> c = a + b;> }
1
intmain()
2
{
3
inta=2;
4
intb=3;
5
intc=a+b;
6
}
Mehr kann man da aus meiner Sicht kaum raus holen!
Vielleicht noch so:
1
intmain()
2
{
3
constinta=2;
4
constintb=3;
5
intc=a+b;
6
}
Sven schrieb:> Wenn ich doch eine Methode aufrufe werden doch Daten auf den Stack> geschrieben und eine Sprunganweisung ausgeführt. Wenn ich dagegen den> Code Sequentiell ausführe, dann benutzt er keine Sprunganweisung und> muss auch nicht notwendigerweise Daten auf dme Stack schrieben und> sichern.
Du meinst "Funktion"..
Gegen den Overhead wurde das Attribut "inline" (Empfehlung an den
Compiler), oder das noch bestimmtere, Compiler spezifische Attribut,
"__attribute__((always_inline))" erfunden.
Mit den Optimierungsstufen -Os bzw. -O2 sollte der Compiler sowieso
alles inlinen, sofern es entweder den Code schrumpft oder schneller
macht, oder eben beides.
Sven schrieb:> main()> {> #SUMME> }
Um Himmels Willen! Bitte nicht! Das ist ja nochmal eine Stufe schlimmer
als Macros. Für so etwas gibt es Unterprogramme aka Funktionen.
1
staticintsumme(constinta,constintb)
2
{
3
return(a+b);
4
}
(Überprüfung auf Überlauf usw. jetzt mal außen vor gelassen)
so define Künstler hatte ich früher auch mal als Kollege.
Auf den ersten Blick alles schön kompakt... aber dann ... pures
Entsetzen :O
Unsere coding guide lines verbieten defines und fordern auf const zu
verwenden.
NichtWichtig schrieb:> Unsere coding guide lines verbieten defines und fordern auf const zu> verwenden.
Leitsatz:
Jedes vermiedene Define ist ein gutes Define.
Jedes vermeidbare Define ist ein böses Define.
NichtWichtig schrieb:> Unsere coding guide lines verbieten defines und fordern auf const zu> verwenden.
Hmmm... warum muss die (Coding-) Welt immer schwarz und weiss sein?
Vermutlich verbietet ihr auch GOTO ;-)
Du solltest ein echtes Beispiel posten. Wenn das der Original-Code war:
Sven schrieb:
1
voidmain(void)
2
{
3
inta,b,c;
4
5
a=2;
6
b=3;
7
c=a+b;
8
}
dann macht sinnloses Zerreißen in Funktionen es nicht besser.
(OK, ist natürlich kein Originalcode, da sinnfrei. Aber was Du daraus
gemacht hast, ist grausam)
Darum wirklich mal eine originale Funktion posten.
Code zu strukturieren bedeutet
- logisch zusammenhängende Codestücke zusammenfassen
- wieder verwendbare Elemente in Funktionen kapseln
- Code zu dokumentieren
- eine Gruppe von wieder verwendbaren Codeblöcken in eigene Libs(.h/.c)
zusammen fassen
- Problemstellungen in logisch zusammenhängende Unteraufgaben zerteilen
und dann in überschaubaren Funktionsblöcken implementieren.
Code zu strukturieren bedeutet nicht, Code zu schreiben und dann einen
Platzhalter generieren, damit es an irgendeiner Stelle kürzer aussieht.
c = a + b; ist weder komplex genug als das es wieder verwendet werden
könnte, noch ergibt sich eine Notwendigkeit, es überschaubarer zu
machen.
"Modularisieren" im eigentlichen Sinn (Code in einzelne, funktional
getrennte Module aufteilen) kann durchaus dazu führen, dass Programme
grösser und/oder langsamer werden.
Gcc kann nur dann wirklich vernünftige Entscheidungen zum Inlining
treffen, wenn es den gesamten relevanten Code "auf einmal" zu sehen
bekommt. Wenn der aufgerufene Code plötzlich in einem anderen Modul
steckt, ist das u.U. nicht mehr der Fall und es kommt ein
Funktionsaufruf mit Prolog/Epilog dazu, wo vorher keiner war. Effekt:
das Programm wird u.U. langsamer und grösser.
LTO sollte das eigentlich vermeiden. Benutzt Du das?
Michael R. schrieb:> Vermutlich verbietet ihr auch GOTO ;-)
Kannst du eine sinnvolle Verwendung für Goto nennen, die nicht durch
sicherere und lesbarere Konstrukte ersetzt werden kann?
Löser schrieb:> Kannst du eine sinnvolle Verwendung für Goto nennen, die nicht durch> sicherere und lesbarere Konstrukte ersetzt werden kann?
Beispielsweise um aus verschachtelten Schleifen rauszuspringen.
Daniel H. schrieb:> Löser schrieb:> Kannst du eine sinnvolle Verwendung für Goto nennen, die nicht durch> sicherere und lesbarere Konstrukte ersetzt werden kann?>> Beispielsweise um aus verschachtelten Schleifen> rauszuspringen.
1
bool_texit=false;
2
while(...)
3
{
4
while(...)
5
{
6
if(exitCondition)
7
{
8
exit=true;
9
break;
10
}
11
}
12
if(exit){break;};
13
}
14
15
...
Meiner Meinung nach sauberer und sicherer. Exit kann auch in jeder
Funktion gleich heißen für den Erkennungswert, bei Labels muss man sich
ein Namensschema ausdenken, damit man auch korrekt springt.
Löser schrieb:> Meiner Meinung nach sauberer und sicherer.
Richtig: DEINER Meinung nach. Meiner Meinung nach nicht :-)
Goto ist nicht böse, nur weil ihr das alle in der Schule gelernt habt.
Löser schrieb:> bool_t exit = false;> while(...)> {> while(...)> {> if(exitCondition)> {> exit = true;> break;> }> }> if(exit) { break; };> }>> ...>> Meiner Meinung nach sauberer und sicherer. Exit kann auch in jeder> Funktion gleich heißen für den Erkennungswert, bei Labels muss man sich> ein Namensschema ausdenken, damit man auch korrekt springt.
Eine Katastrophe. Diese Dogmen gehen mir gewaltig auf die Nerven. Auch
ein goto kann - wie gezeigt - sinnvoll verwendet werden. Das hier ist
einfach unleserlich - wobei man eher diese verschachtelten Schleifen
meiden sollte.
Alle kriegen eingetrichtert, dass goto böse sei, nur weil Anfänger es
nicht wissen sinvoll einzusetzen und Spaghetticode produzieren. Und alle
plappern es nach. Kein gutes Zeichen für einen selbstsständig denkenden
Ingenieur.
Arduino F. schrieb:> Ich kenne das so:> Die Regeln sind schwarz weiß.> Ausnahmen müssen begründet und abgesegnet werden.
Du gehst also zum Chef/Vorgesetzten und fragst "Darf ich hier
ausnahmsweise mal ein define verwenden?"? Also da/so möchte ich nicht
arbeiten. Kriegst du auch eine Abmahnung, solltest du dochmal
unerlaubterweise ein goto/define verwenden? Wird dein Code Zeile für
Zeile überprüft, ob du nur erlaubte C-ELemente verwendet hast? Und das
bei Arduino, wo doch eh egal ist was man eintippt..
Nils N. schrieb:> Du gehst also zum Chef/Vorgesetzten und fragst "Darf ich hier> ausnahmsweise mal ein define verwenden?"? Also da/so möchte ich nicht> arbeiten. Kriegst du auch eine Abmahnung, solltest du dochmal> unerlaubterweise ein goto/define verwenden? Wird dein Code Zeile für> Zeile überprüft, ob du nur erlaubte C-ELemente verwendet hast? Und das> bei Arduino, wo doch eh egal ist was man eintippt..
Du bist doch nicht ganz dicht!
Auch wenn dir das fremd sein mag...
Es gibt einen deutlichen Unterschied zwischen Richtlinien und Dogmen.
Ich glaube nicht, dass ein Team ohne Richtlinien erfolgreich arbeiten
kann.
Michael R. schrieb:> NichtWichtig schrieb:>> Unsere coding guide lines verbieten defines und fordern auf const zu>> verwenden.>> Hmmm... warum muss die (Coding-) Welt immer schwarz und weiss sein?
Genau meine Rede. Schwarz/weiß ist für Anfänger gut, damit sie nicht
gleich in jedes Fettnäpfchen treten, weil sie ein Feature falsch
benutzen. Aber es gibt sehr wenige Features der Sprache, die wirklich
niemals sinnvoll sind.
Löser schrieb:> Meiner Meinung nach sauberer und sicherer.
Warum? Ich finde es unübersichtlicher durch die zusätzlich nötige
Hilfsvariable. Solche Hilfsvariablen sind für mich Krücken, die ich
gerne vermeide. Und was soll daran sicherer sein?
Für mich klingt die Aussage, als ob dir mal eingetrichtert wurde, dass
goto der Hölle entstamme und unter allen Umständen zwingend zu vermeiden
sei, weil sonst die Apokalypse droht oder sowas.
> Exit kann auch in jeder Funktion gleich heißen für den Erkennungswert,> bei Labels muss man sich ein Namensschema ausdenken, damit man auch> korrekt springt.
Nein, warum sollte man das müssen? Das kann auch in jeder Funktion
gleich heißen.
Arduino F. schrieb:> Du bist doch nicht ganz dicht!
Das waren deine Worte: Ausnahmen müssen begründet und abgesegnet werden.
Und wir redeten hier über defines. Also wenn du ein define verwenden
willst, muss das abgesegnet werden.
In meiner letzten Firma gab es auch den Versuch, solche
Anweisungen/Richtlinien bzgl. Formatierung durchzusetzen. Letztenendes
war das aber eher hinderlich als nützlich und ist somit wieder in der
Schublade verschwunden.
Rolf M. schrieb:> weil sonst die Apokalypse droht
Mindestens! Aber die Große!
Und um der kleinen Apokalypse (das ist die ohne Pferde) zu entgehen,
verbietet man am besten auch "early return"! Sicher ist sicher...
irgendwas läuft da in der Ausbildung der "Coder" falsch...
Nils N. schrieb:> Also wenn du ein define verwenden> willst, muss das abgesegnet werden.
Die Frage ist, willst du es wirklich wissen, oder nur Streit...
Wenn Streit, dann sollten wir das hier schnell beenden.
Eine der Leitlinien habe ich hier schon genannt:
Arduino F. schrieb:> Leitsatz:> Jedes vermiedene Define ist ein gutes Define.> Jedes vermeidbare Define ist ein böses Define.
Die beiden Sätze haben sowas wie eine Hysterese...
Den Bereich der unvermeidbaren Defines.
Und den Bereich wo das krampfhafte vermeiden von Defines zu Nachteilen
irgendwelcher Art führt.
Was der TE mit Defines anstellt wäre bei uns ein NoGo.
Was für Defines gilt, gilt auch für Gotos.
Z.B. Beitrag "Re: Lesbarer ProgrammCode"
Was da mit dem Exitflag gemacht wird, heißt bei uns "Eiertanz".
Und ja, mein Code wird von anderen geprüft. Das wird nicht eingefordert,
sondern passiert automatisch. Es müssen ja auch meist andere daran/damit
weiterarbeiten.
Im Grunde muss man jederzeit, jedem im Team, erklären können was, und
warum man es so getan hat, oder tun will. Die anderen melden sich dann
schon, wenn es bessere/elegantere Wege gibt.
Im Grunde bringt einen das krampfhafte festhalten an Dogmen nicht
weiter.
Die Leitsätze und Regeln sind eine Vereinbarung, welche einem das Leben
erleichtern. Die Teamarbeit erleichtern.
Ein bisschen so, wie der Unterschied zwischen einem gepflasterten Weg,
und der Kugel am Bein.
Vergleiche es mit der durchgezogenen Mittellinie auf einer Straße. Es
ist für alle Verkehrsteilnehmer angenehm, wenn sich jeder daran hält.
Die Linie ist ja meist auch mit Grund da.
Aber dennoch, darf/muss ich sie in manchen Situationen überfahren. Diese
Einsicht darf allerdings nicht dazu führen, dass ab dem ersten
Überfahren, alle weißen Linien dieser Welt ignoriert werden.
Nils N. schrieb:> In meiner letzten Firma gab es auch den Versuch, solche> Anweisungen/Richtlinien bzgl. Formatierung durchzusetzen. Letztenendes> war das aber eher hinderlich als nützlich und ist somit wieder in der> Schublade verschwunden.
Ja, das hört sich so an, als wäre das bei euch schief gelaufen.
Vielleicht zu übertrieben, zu krampfhaft..
Eine Weisung "von oben"?
Oliver S. schrieb:> Löser schrieb:>> Meiner Meinung nach sauberer und sicherer.>> Und weil das so super sauber und sicher ist, hat man in C++ exceptions> erfunden.>> Oliver
Exceptionhandling kostet aber schon einiges mehr an Rechenzeit und ist
in C nicht verfügbar. Das sollte man hier fairerweise auch mit
betrachten.
Grüße Oliver
Oliver S. schrieb:> Und weil das so super sauber und sicher ist, hat man in C++ exceptions> erfunden.
Exceptions haben leider so gar nichts mit mehr oder weniger sinnvollen
Anwendung von Goto zu tun.
Und ich behaupte, man kann mit Exceptions (oder dem Werfen ebensolcher)
Code viel zuverlässiger unlesbar machen als mit Goto.
Arduino F. schrieb:> Nils N. schrieb:>> Also wenn du ein define verwenden>> willst, muss das abgesegnet werden.>> Die Frage ist, willst du es wirklich wissen, oder nur Streit...> Wenn Streit, dann sollten wir das hier schnell beenden.
Wieso? Das hast du doch selbst geschrieben:
Arduino F. schrieb:> Ausnahmen müssen begründet und abgesegnet werden.
Also heißt das, du musst zu dem gehen, der die Autorität darüber hat und
bei dem beantragen, dass du ein define machen darfst. Oder was sonst
verstehst du unter "abgesegnet werden"?
> Eine der Leitlinien habe ich hier schon genannt:>> Arduino F. schrieb:>> Leitsatz:>> Jedes vermiedene Define ist ein gutes Define.>> Jedes vermeidbare Define ist ein böses Define.>> Die beiden Sätze haben sowas wie eine Hysterese...> Den Bereich der unvermeidbaren Defines.> Und den Bereich wo das krampfhafte vermeiden von Defines zu Nachteilen> irgendwelcher Art führt.
Das ist ja ok, erklärt aber noch nicht, wie das "abgesegnet werden"
funktioniert.
> Im Grunde bringt einen das krampfhafte festhalten an Dogmen nicht> weiter.> Die Leitsätze und Regeln sind eine Vereinbarung, welche einem das Leben> erleichtern. Die Teamarbeit erleichtern.> Ein bisschen so, wie der Unterschied zwischen einem gepflasterten Weg,> und der Kugel am Bein.
Ja. Von jeder Regel gibt es Ausnahmen, da sich nicht alles zu 100%
sinnvoll in ein starres Regelwerk pressen lässt. Kann man machen, aber
wenn man Dinge komplizierter macht, nur weil die Regel die Vereinfachung
verbietet, ist was falsch gelaufen.
> Vergleiche es mit der durchgezogenen Mittellinie auf einer Straße. Es> ist für alle Verkehrsteilnehmer angenehm, wenn sich jeder daran hält.> Die Linie ist ja meist auch mit Grund da.>> Aber dennoch, darf/muss ich sie in manchen Situationen überfahren. Diese> Einsicht darf allerdings nicht dazu führen, dass ab dem ersten> Überfahren, alle weißen Linien dieser Welt ignoriert werden.
Allerdings muss das Überfahren der Linie nicht vorher abgesegnet werden,
denn das wäre etwas unpraktisch. ;-)
Oliver J. schrieb:> Exceptionhandling kostet aber schon einiges mehr an Rechenzeit und ist> in C nicht verfügbar.
Kann man mit setjmp nachbilden. exceptions4c macht das sehr elegant:
https://github.com/guillermocalvo/exceptions4c
Man kann in C eben schon wirklich alles machen. Wenn man es wirklich
beherrscht, fragt man sich nichtmehr wie etwas möglich ist, sondern
nurnoch wie man es am liebsten aufschreiben will. Wenn man ersteinmal
soweit ist, ist Programmieren wie das Mahlen eines Kunstwerks, man steht
über dem Syntax und den Einschränkungen, über den Regeln der
Programmiersprache, und kann alles tun, was die Vorstellungskraft
erlaubt. (wobei man das trotzdem nicht immer tun sollte)
Daniel A. schrieb:> Oliver J. schrieb:>> Exceptionhandling kostet aber schon einiges mehr an Rechenzeit und ist>> in C nicht verfügbar.>> Kann man mit setjmp nachbilden. exceptions4c macht das sehr elegant:> https://github.com/guillermocalvo/exceptions4c>> Man kann in C eben schon wirklich alles machen. Wenn man es wirklich> beherrscht, fragt man sich nichtmehr wie etwas möglich ist, sondern> nurnoch wie man es am liebsten aufschreiben will.
Oder man fragt sich, ob man nicht lieber eine Sprache nimmt, bei der man
das nicht zu Fuß machen muss. Nicht falsch verstehen: Ich mache viel in
C, aber die ganzen Sprachmittel von C++ will ich damit nicht nachbilden
müssen. Da gehören vor allem gerade so Sachen wie Exceptions oder
Polymorphie dazu.
Und spätestens bei Templates kann man auch nicht mehr alles in C machen,
ohne sich noch einen eigenen Codegenerator zu schreiben.
> Wenn man ersteinmal soweit ist, ist Programmieren wie das Mahlen eines> Kunstwerks,
Das trifft's ein bisschen, wenn auch nicht auf die von dir gewünschte
Art (du hast vermutlich "Malen" und nicht "Mahlen" gemeint). ;-)
Rolf M. schrieb:> Wieso? Das hast du doch selbst geschrieben:Rolf M. schrieb:> Also heißt das, du musst zu dem gehen, der die Autorität darüber hat und> bei dem beantragen, dass du ein define machen darfst. Oder was sonst> verstehst du unter "abgesegnet werden"?
Deine Art zu zitieren/lesen ist recht seltsam...
Das einzige, was deine Frage wirklich beantwortet, wird ignoriert.
Es macht auch keinen Sinn auf "vorher Absegnen" zu beharren.
Denn ganz offensichtlich habe ich was anderes gemeint, als du darunter
verstehen möchtest. Und "vorher" habe ich schon gar nicht gesagt.
Bitte streiche das Wort "Absegnen" in meinen Texten, bis wir uns über
die Semantik geeinigt haben.
Hier nochmal, denn deutlicher kann ich es nicht:
Arduino F. schrieb:> Und ja, mein Code wird von anderen geprüft. Das wird nicht eingefordert,> sondern passiert automatisch. Es müssen ja auch meist andere daran/damit> weiterarbeiten.>> Im Grunde muss man jederzeit, jedem im Team, erklären können was, und> warum man es so getan hat, oder tun will. Die anderen melden sich dann> schon, wenn es bessere/elegantere Wege gibt.
Hat also wenig mit Hierarchie, oder so, zu tun...
Eher anders rum, denn gerade Neueinsteiger hinterfragen den Code.
Die Erfahrenen wissen, dass es zu fast jedem Problem mehrere Lösungen
gibt. Und sie sehen auch, recht schnell, ob die gewählte Lösung
tragfähig ist.
Arduino F. schrieb:> Rolf M. schrieb:>> Also heißt das, du musst zu dem gehen, der die Autorität darüber hat und>> bei dem beantragen, dass du ein define machen darfst. Oder was sonst>> verstehst du unter "abgesegnet werden"?>> Deine Art zu zitieren/lesen ist recht seltsam...> Das einzige, was deine Frage wirklich beantwortet, wird ignoriert.
Mir war nicht klar, dass das die Antwort sein sollte, da ich unter
"absegnen" was anderes verstanden hatte.
Arduino F. schrieb:> Es macht auch keinen Sinn auf "vorher Absegnen" zu beharren.> Denn ganz offensichtlich habe ich was anderes gemeint, als du darunter> verstehen möchtest.
Ja, ganz offensichtlich. Deshalb hab ich ja auch explizit gefragt, was
du damit gemeint hast:
Rolf M. schrieb:> Oder was sonst verstehst du unter "abgesegnet werden"?> Und "vorher" habe ich schon gar nicht gesagt.
Gehört für mich irgendwie dazu. Ich frage um Erlaubnis, etwas zu tun,
bevor ich es tue und nicht erst, nachdem ich es schon getan habe. Und
ich (und andere wohl auch) dachte, genau das hättest du mit "abgesegnet
werden" gemeint: Dass du vorher um Erlaubnis fragst.
Michael R. schrieb:> NichtWichtig schrieb:>> Unsere coding guide lines verbieten defines und fordern>> auf const zu verwenden.>> Hmmm... warum muss die (Coding-) Welt immer schwarz und> weiss sein?
Weil die formale Logik auch nur schwarz und weiss ist:
Entweder das Sprachkonstrukt liefert definierten Compiler-
output, oder es tut es nicht.
> Vermutlich verbietet ihr auch GOTO ;-)
Ich kenne kein überzeugendes Argument, es nicht zu tun. Hier
im Thread kam jedenfalls noch keins :)
(Und dass man in der Schule gelernt hat, Goto sei böse,
heisst ja nicht automatisch, dass es in Wahrheit gut ist,
nicht wahr?! Nicht ALLES, was man in der Schule lernt, ist
falsch.)
Possetitjel schrieb:>> Hmmm... warum muss die (Coding-) Welt immer schwarz und>> weiss sein?>> Weil die formale Logik auch nur schwarz und weiss ist:> Entweder das Sprachkonstrukt liefert definierten Compiler-> output, oder es tut es nicht.
Es ging hier aber nicht darum, ob etwas formalsprachlich korrekt ist
oder nicht, sondern darum, ob es sinnvoll ist, korrekte Konstrukte
pauschal zu verbieten, weil sie von Anfängern gerne falsch benutzt
werden.
>> Vermutlich verbietet ihr auch GOTO ;-)>> Ich kenne kein überzeugendes Argument, es nicht zu tun. Hier> im Thread kam jedenfalls noch keins :)
Doch, beide Situationen, in denen es sinnvoll sein kann, wurden genannt.
> (Und dass man in der Schule gelernt hat, Goto sei böse,> heisst ja nicht automatisch, dass es in Wahrheit gut ist,> nicht wahr?! Nicht ALLES, was man in der Schule lernt, ist> falsch.)
Das hat auch keiner behauptet. Aber umgekehrt sollte man auch nicht
alles, was man in der Schule gelernt hat, unreflektiert übernehmen und
zum Dogma machen. Man darf Regeln auch hinterfragen.
Nils hat es gut auf den Punkt gebracht:
Nils N. schrieb:> Alle kriegen eingetrichtert, dass goto böse sei, nur weil Anfänger es> nicht wissen sinvoll einzusetzen und Spaghetticode produzieren. Und alle> plappern es nach. Kein gutes Zeichen für einen selbstsständig denkenden> Ingenieur.
Rolf M. schrieb:> Es ging hier aber nicht darum, ob etwas formalsprachlich> korrekt ist oder nicht, sondern darum, ob es sinnvoll ist,> korrekte Konstrukte pauschal zu verbieten, weil sie von> Anfängern gerne falsch benutzt werden.
Wenn man ernsthaft darüber diskutieren kann, die Verwendung
eines formalsprachlich korrekten Konstruktes zu verbieten,
dann ist die Sprachdefinition schlecht.
Und genau das ist auch meine (Außenseiter-)Meinung.
Da man aber i.d.R. nicht die Macht hat, das Übel an der
Wurzel zu packen, beschränkt man sich auf die Symptom-
behandlung und verbietet eben die Verwendung von goto.
Gäbe es das Sprachelement gar nicht, gäbe es auch die
Diskussion nicht, und niemand würde sich aufregen.
>>> Vermutlich verbietet ihr auch GOTO ;-)>>>> Ich kenne kein überzeugendes Argument, es nicht zu tun.>> Hier im Thread kam jedenfalls noch keins :)>> Doch, beide Situationen, in denen es sinnvoll sein kann,> wurden genannt.
Es ging mir nicht darum, dass das Sprachelement in manchen
Fällen hübsch und nett sein kann (das gestehe ich ja zu) --
es ging darum, dass der Schaden meiner Meinung nach den
Nutzen weit überwiegt und dass es deshalb sehr wohl sinnvoll
ist, die Verwendung zu verbieten.
Um das nochmal klar zu sagen: Die Tatsache, dass es den
Experten in manchen Fällen eine etwas elegantere
Formulierung erlaubt, ist keine hinreichende Begründung,
ein Sprachelement in den Standard aufzunehmen. Dazu wäre
schon etwas mehr notwendig.
>> (Und dass man in der Schule gelernt hat, Goto sei böse,>> heisst ja nicht automatisch, dass es in Wahrheit gut ist,>> nicht wahr?! Nicht ALLES, was man in der Schule lernt, ist>> falsch.)>> Das hat auch keiner behauptet. Aber umgekehrt sollte man> auch nicht alles, was man in der Schule gelernt hat,> unreflektiert übernehmen und zum Dogma machen.
Dass das eine handfeste Beleidigung ist, ist Dir bewusst?
Dass das meine Neigung, über die Gründe meiner Meinung
zu diskutieren, ggf. negativ beeinflussen könnte, ist
beabsichtigt?
> Man darf Regeln auch hinterfragen.
Ja.
Und ich darf dabei auch zu anderen Ergebnissen kommen als Du,
und ich darf diese abweichende Meinung sogar öffentlich
vertreten.
Nun, den Sven scheinen wir ja gründlich verschreckt zu haben. Neugierig
wäre ich allerdings schon, was er wirklich meint, zu verbessern. Sein
bisheriges Beispiel brachte leider keinerlei Klarheit darüber.
Possetitjel schrieb:> dass der Schaden meiner Meinung nach den> Nutzen weit überwiegt und dass es deshalb sehr wohl sinnvoll> ist, die Verwendung zu verbieten.
Ja, C ist ein scharfes Messer und scharfe Messer sollten verboten
werden. Schliesslich könnte man sich dran verletzen.
Auf die paar Chirurgen, die mit scharfen Messern umgehen können, kommt's
nicht an, die können doch - wie jeder andere auch - stattdessen
Plastiklöffel nehmen.
Possetitjel schrieb:> (Und dass man in der Schule gelernt hat, Goto sei böse,> heisst ja nicht automatisch, dass es in Wahrheit gut ist,> nicht wahr?! Nicht ALLES, was man in der Schule lernt, ist> falsch.)
Manche Annahmen/Behauptungen/Regeln sind so dermaßen falsch, dass noch
nicht einmal das Gegenteil richtig ist.
Markus F. schrieb:> Possetitjel schrieb:>> dass der Schaden meiner Meinung nach den Nutzen weit>> überwiegt und dass es deshalb sehr wohl sinnvoll ist,>> die Verwendung zu verbieten.>> Ja, C ist ein scharfes Messer
Nein.
C ist eine alte Drehbank, ohne Futterschutz, ohne
Drehmomentsicherung, ohne Not-Aus und mit
Transmissionsantrieb.
> und scharfe Messer sollten verboten werden.
Nein, s.o.
> Auf die paar Chirurgen, die mit scharfen Messern umgehen> können, kommt's nicht an, [...]
Du musst weder meiner Meinung sein noch meinen Standpunkt
nachvollziehen können -- aber es wäre schön, wenn Du meine
Argumente wenigstens zur Kenntnis nehmen und verstehen
würdest.
Wenn es Fälle gäbe, in denen goto NOTWENDIG, d.h.
UNVERZICHTBAR ist, dann könnte man ja darüber reden.
Wenn es aber nur in wenigen Fällen zu ELEGANTEREN Programmen
führt, stimmt das Aufwand-Nutzen-Verhältnis nicht.
Possetitjel schrieb:> Wenn es Fälle gäbe, in denen goto NOTWENDIG, d.h.> UNVERZICHTBAR ist, dann könnte man ja darüber reden.
Wenn es einen Grund geben würde, es zu verbieten, dann würde man es aus
dem Standard werfen.
Possetitjel schrieb:> Rolf M. schrieb:>>> Es ging hier aber nicht darum, ob etwas formalsprachlich>> korrekt ist oder nicht, sondern darum, ob es sinnvoll ist,>> korrekte Konstrukte pauschal zu verbieten, weil sie von>> Anfängern gerne falsch benutzt werden.>> Wenn man ernsthaft darüber diskutieren kann, die Verwendung> eines formalsprachlich korrekten Konstruktes zu verbieten,> dann ist die Sprachdefinition schlecht.
Ich bin ja nicht der, der die Nutzung solcher Konstrukte verbieten will.
> Gäbe es das Sprachelement gar nicht, gäbe es auch die> Diskussion nicht, und niemand würde sich aufregen.
Naja, höchstens darüber, dass es für bestimmte Dinge nur unnötig
umständliche Lösungen gibt. Ist ja bei anderen Sachen, die es in C nicht
gibt, auch so.
> Es ging mir nicht darum, dass das Sprachelement in manchen> Fällen hübsch und nett sein kann (das gestehe ich ja zu) --> es ging darum, dass der Schaden meiner Meinung nach den> Nutzen weit überwiegt und dass es deshalb sehr wohl sinnvoll> ist, die Verwendung zu verbieten.
Das sehe ich eben anders. Ich finde es recht unsinnig, ein existierendes
Sprachfeature an einer Stelle, wo es die sinnvollste Lösung wäre, nur
deshalb nicht einzusetzen, weil man es für böse erklärt hat.
> Um das nochmal klar zu sagen: Die Tatsache, dass es den> Experten in manchen Fällen eine etwas elegantere> Formulierung erlaubt, ist keine hinreichende Begründung,> ein Sprachelement in den Standard aufzunehmen. Dazu wäre> schon etwas mehr notwendig.
Programmierung ist ein kompliziertes Handwerk. Da sind manchmal auch
Werkzeuge sinnvoll, mit denen nur Experten richtig umgehen können. Für
eine CNC-Fräse muss man auch erstmal lernen, wie man sie benutzt. Das
heißt aber nicht, dass man deshalb alle - auch die, die den Umgang
damit gelernt haben - zwingen sollte, stattdessen alles mit der Feile zu
bearabeiten. Den Azubi, der gestern angefangen hat, lässt man aber
besser nicht an die Maschine. Klar, ist ein etwas überzogener Vergleich,
aber macht deutlich, was ich meine: Nur weil es auch Leute gibt, die ein
bestimmtes Werkzeug nicht benutzen können, sollte man deshalb nicht
gleich auch alle anderen dazu zwingen es nicht zu benutzen.
>> Das hat auch keiner behauptet. Aber umgekehrt sollte man>> auch nicht alles, was man in der Schule gelernt hat,>> unreflektiert übernehmen und zum Dogma machen.>> Dass das eine handfeste Beleidigung ist, ist Dir bewusst?
Wo du da eine Beleidigung zu sehen glaubst, vermag ich nicht zu
erkennen. Es war jedenfalls nicht meine Absicht, irgendwen zu
beleidigen.
>> Man darf Regeln auch hinterfragen.>> Ja.>> Und ich darf dabei auch zu anderen Ergebnissen kommen als Du,> und ich darf diese abweichende Meinung sogar öffentlich> vertreten.
Natürlich. Nur habe ich bei den meisten von denen, die goto vehement
ablehnen, nicht den Eindruck, dass das aufgrund selbst gebildeter
Meinung passiert.
Possetitjel schrieb:> Wenn es Fälle gäbe, in denen goto NOTWENDIG, d.h.> UNVERZICHTBAR ist, dann könnte man ja darüber reden.
Zwingend notwendig sind nur sehr wenige Sprachfeatures (auch Brainfuck
ist Touring-vollständig). Deshalb muss man ja nicht gleich alles andere
abschaffen.
> Wenn es aber nur in wenigen Fällen zu ELEGANTEREN Programmen> führt, stimmt das Aufwand-Nutzen-Verhältnis nicht.
Welcher Aufwand?
Ich gebe gern zu, dass goto eigentlich nicht notwendig ist (bzw. -
s.u. nicht notwendig sein sollte) und wenn, dann nur sehr sparsam
eingesetzt werden sollte.
Ich gestehe, ich habe in - ich weiss nicht - mehr als dreissig Jahren
vielleicht 100x goto verwendet (pfui!). Nicht, weil ich's unbedingt
gebraucht hätte, sondern weil es in der Situation die einfachere,
leichter lesbare, einfach bessere Lösung war.
Tatsächlich war sicher deutlich mehr als die Hälfte davon kein eigener
Code, sondern der Pfusch anderer Leute, die vor lauter Verschachtelung
am Ende vergessen haben, allokierte Ressourcen frei zu geben. Wenn man
so was reparieren muss, ohne gleich alles neu zu schreiben (und damit
die gesamte Testmaschinerie anzuwerfen), ist goto Gold wert. In grossen
Serveranwendungen werden solche Fehler oft erst im Produktivbetrieb
gefunden - und dann muss es auch mal schnell und einfach gehen.
Was mich stört ist der sture Dogmatismus, der hier durchscheint.
Sollte man nicht auch switch verbannen, denn das ist doch nur ein
berechnetes goto. Und Mann kann da Fehler machen, z.B. break vergessen.
Man könnte auch schreiben verbieten, denn manche halten sich nicht an
die Regeln, die sie in der Schule hätten lernen sollen.
Meine Software wird von Software ùberprüft. Die will aber nicht einer
Diskussion stellen und meckert nur Dinge, an die sie auch versteht. Und
da sie die Sprache, die sie prüfen soll, nicht beherrscht, wird eben
weniger straight forward programmiert. Ein echter Erfolg!
Switch schrieb:> Sollte man nicht auch switch verbannen, denn das ist doch nur ein> berechnetes goto.
Aber es ist begrenzt wo du hinspringen kannst, das ist der entscheidende
Unterschied! Mit Goto kannst du sogar in eine ganz andere Funktion
springen.
Arduino F. schrieb:> Possetitjel schrieb:>> Wenn es Fälle gäbe, in denen goto NOTWENDIG, d.h.>> UNVERZICHTBAR ist, dann könnte man ja darüber reden.>> Wenn es einen Grund geben würde, es zu verbieten, dann> würde man es aus dem Standard werfen.
Nee, das ist eben der Denkfehler. Es JETZT rauswerfen
zu wollen wäre idiotisch, denn es würde alten Code
kaputtmachen.
Die Hürde, es nachträglich herauszuwerfen, ist viel höher
als die, es von vornherein gar nicht hineinzuschreiben.
Arduino F. schrieb:> Leitsatz:> Jedes vermiedene Define ist ein gutes Define.> Jedes vermeidbare Define ist ein böses Define.
was ist an #defines schlecht?
#define WENN if
#define GLEICH ==
#define DOCHANDERS else
WENN( a GLEICH b )
{
printf("a ist gleich b");
}
DOCHANDERS
{
printf("a ist leider nicht gleich b");
}
ich habs zwar noch nie genutzt, aber wer mit Englisch Probleme hat why
not? :)
Wenn du solche Textersetzungen benötigst, dann ist #define genau das
richtige für dich.
Denn in dem Punkt ist es alternativlos.
Die wichtigsten Nachteile von Präprozessormacros sind:
1. Kryptische Fehlermeldungen in Zeilen, wo das Macro genutzt wird.
Nicht dort wo es erstellt wurde.
2. Keine Typeprüfung von Parametern usw.
3. Es erschwert das Debuggen, denn der Debugger bekommt die Macros nicht
zu sehen. Bzw. kann nicht damit umgehen.
Habe ich noch was vergessen?
Bestimmt!
z.B. man baut sich leicht unerwünschte/unerwartete Seiteneffekte ein.
Und landet dann bei Punkt 3.
Possetitjel schrieb:> Wenn es Fälle gäbe, in denen goto NOTWENDIG, d.h. UNVERZICHTBAR ist,> dann könnte man ja darüber reden.> Wenn es aber nur in wenigen Fällen zu ELEGANTEREN Programmen führt,> stimmt das Aufwand-Nutzen-Verhältnis nicht.
Das heißt dann, das man auch while und do-while rausschmeißen sollte,
weil for das alles ja auch abdeckt? ;)
Possetitjel schrieb:> Wenn man ernsthaft darüber diskutieren kann, die Verwendung> eines formalsprachlich korrekten Konstruktes zu verbieten,> dann ist die Sprachdefinition schlecht.
Nein, sondern dann wurde die Sprache eben von Profis entworfen, die auch
genau wußten, wieso sie goto aufgenommen haben. Wenn ich mir ansehe, wie
man in Pascal üblicherweise gestackte Fehlerbehandlung ohne goto macht,
oder auch Ausstieg aus geschachtelten Schleifen, dann ist das noch
unübersichtlicher. Das läuft dann nämlich auf tief geschachtelte ifs,
Code-Duplikation und/oder absurde Hilfs-Variablen hinaus.
Zudem haben 95.34% der Leute, die goto wegen Dijkstras legendärem "goto
considered harmful"-Papers verreißen, den Aufsatz überhaupt nicht
begriffen, sondern plappern nur nach, was sie irgendwo aufgeschnappt
haben.
Das goto, worauf sich Dijkstra damals bezogen hat, und was tatsächlich
zu Spaghetti geführt hat, war nämlich ein gänzlich anderes. Damals
konnte man noch anhand absoluter Zeilennummern quer durch das ganze
Programm springen.
Das hat so gut wie nichts mit C-goto zu tun, was man nur innerhalb einer
Funktion benutzen kann, und dann auch nur mit benannten Labels statt
Zeilennummern.
Das Äquivalent des damals kritisierten gotos wäre in C nicht goto,
sondern eher setjmp/longjmp (nur in besser). Das kennen viele Leute
nichtmal dem Namen nach, und das ist auch gut so. Denn das ist ein noch
viel schärferes Schwert als goto, was man für Exception-Handling in C
nutzen kann.
Richtig ist aber auch, daß Rückwärtssprünge mit goto bedenklich sind,
auch in C. Das kann man meistens mit einer while-Schleife umgehen, die
einen Zustandsautomaten enthält. Der ist dann auch übersichtlicher. So
mache ich jedenfalls algorithmische Rückwärtssprünge, sofern ist nicht
das letzte bißchen an Performance gerade an der Stelle brauche. Schon
weil ein Zustandsautomat ein Idiom ist, was jeder nachfolgende
Programmierer kennt und sofort versteht.
Selbst Vorwärtssprünge mit goto sind in den allermeisten Fällen auf
Fehlerbehandlung begrenzt. Computed goto, also goto anhand eines
Label-Arrays per Index, ist leider immer noch nicht Teil des C-Standards
(GCC und Clang können es). Das kann man aber algorithmisch gut
gebrauchen, wenn es auf Performance ankommt. Sowas betrifft etwa
Interpreter, Python sei genannt.
Arduino F. schrieb:> Wenn du solche Textersetzungen benötigst, dann ist #define genau> das richtige für dich. Denn in dem Punkt ist es alternativlos.
Man kann sogar statische Webseiten mit einem C-Compiler verwalten, indem
man im Roh-HTML includes und Macros nutzt und das dann durch einen
C-Compiler jagt, bei dem man aber nur die Stufe des Präprozessors nutzt.
Daniel A. schrieb:> Löser schrieb:>> Mit Goto kannst du sogar in eine ganz andere Funktion>> springen.>> Wie machst du das denn? Schwarze Magie?
So wie immer, wenn Ahnungslosigkeit im Spiel ist.
Dann ist die Überraschung groß, wenn man's dann doch mal probiert.
Switch schrieb:> So wie immer, wenn Ahnungslosigkeit im Spiel ist.
Ja. Wie man hier im Thread sieht, scheint ein Großteil der Ablehnung von
goto auch schlicht durch Unwissen / Fehlinformation ausgelöst zu sein.
Hier mal die Definition aus der C-Norm:
6.2.1 Scopes of Identifiers
[....]
3 A label name is the only kind of identifier that has function scope.
It can be used (in a goto statement) anywhere in the function in which
it appears, and is declared implicitly by its syntactic appearance
(followed by a : and a statement).
Sprich: Ein Label ist nur lokal innerhalb der Funktion sichtbar, in der
es deklariert ist. Ich kann selbstverständlich den selben Namen in
anderen Funktionen wiederverwenden, und ich kann damit nicht über
Funktionsgrenzen hinweg springen.
Rolf M. schrieb:> 6.2.1 Scopes of Identifiers
ich zitiere noch einen weiteren Teil aus dem Standard (draft N1570),
damit es auch wirklich alle verstehen.
1
6.8.6.1 The goto statement
2
3
Constraints
4
The identifier in a goto statement shall name a label located somewhere in the enclosing
5
function. A goto statement shall not jump from outside the scope of an identifier having
6
a variably modified type to inside the scope of that identifier.
7
8
Semantics
9
A goto statement causes an unconditional jump to the statement prefixed by the named
Switch schrieb:> Sollte man nicht auch switch verbannen, denn das ist doch nur ein> berechnetes goto. Und Mann kann da Fehler machen, z.B. break vergessen.
man kann mit einem switch noch viel wildere Sachen machen:
https://de.wikipedia.org/wiki/Duff%E2%80%99s_Device
Markus F. schrieb:> Switch schrieb:>> Sollte man nicht auch switch verbannen, denn das ist doch nur ein>> berechnetes goto. Und Mann kann da Fehler machen, z.B. break vergessen.>> man kann mit einem switch noch viel wildere Sachen machen:> https://de.wikipedia.org/wiki/Duff%E2%80%99s_Device
Darum sollte man es verbieten.
Genau wie alles, was Einfachgestrickte nicht verstehen. Es ist nämlich
unfair, daß die mit den Anderen verglichen werden.
/Ironie off
Nico W. schrieb:> Possetitjel schrieb:>> Wenn es Fälle gäbe, in denen goto NOTWENDIG, d.h. UNVERZICHTBAR>> ist, dann könnte man ja darüber reden.>> Wenn es aber nur in wenigen Fällen zu ELEGANTEREN Programmen>> führt, stimmt das Aufwand-Nutzen-Verhältnis nicht.>> Das heißt dann, das man auch while und do-while rausschmeißen> sollte, weil for das alles ja auch abdeckt? ;)
Nein. "for" und "Eleganz" ist ein inhärenter Widerspruch. ;)
Man sollte "for" als Ausgeburt eines Sprachsadisten verbieten
und nur "while" und "do-while" erlauben...
Rolf M. schrieb:> Possetitjel schrieb:>> Rolf M. schrieb:>>>>> Es ging hier aber nicht darum, ob etwas formalsprachlich>>> korrekt ist oder nicht, sondern darum, ob es sinnvoll ist,>>> korrekte Konstrukte pauschal zu verbieten, weil sie von>>> Anfängern gerne falsch benutzt werden.>>>> Wenn man ernsthaft darüber diskutieren kann, die Verwendung>> eines formalsprachlich korrekten Konstruktes zu verbieten,>> dann ist die Sprachdefinition schlecht.>> Ich bin ja nicht der, der die Nutzung solcher Konstrukte> verbieten will.
Ich auch nicht -- aber wir diskutieren ja (getriggert durch
den Scherz von Michael) darüber, ob das ggf. legitim wäre
oder nicht.
Bei "int" oder "struct" verbietet sich diese Diskussion, weil
klar ist (?!), dass man darauf nicht verzichten will -- aber
bei "goto" ist das ganz offensichtlich nicht so eindeutig.
>> Gäbe es das Sprachelement gar nicht, gäbe es auch die>> Diskussion nicht, und niemand würde sich aufregen.>> Naja, höchstens darüber, dass es für bestimmte Dinge nur> unnötig umständliche Lösungen gibt. Ist ja bei anderen> Sachen, die es in C nicht gibt, auch so.
Ja, stimmt.
Ich denke aber, das ist quasi eine Naturnotwendigkeit, denn
keine Programmiersprache kann ALLE Konstrukte, die irgendwann
mal gebraucht werden, gleichermaßen einfach und elegant
bereitstellen.
Man muss sich also auf einen gewissen Kernbereich beschränken,
und alles, was da nicht dazugehört, geht eben nur umständlicher.
>> Es ging mir nicht darum, dass das Sprachelement in manchen>> Fällen hübsch und nett sein kann (das gestehe ich ja zu) -->> es ging darum, dass der Schaden meiner Meinung nach den>> Nutzen weit überwiegt und dass es deshalb sehr wohl sinnvoll>> ist, die Verwendung zu verbieten.>> Das sehe ich eben anders. Ich finde es recht unsinnig, ein> existierendes Sprachfeature an einer Stelle, wo es die> sinnvollste Lösung wäre, nur deshalb nicht einzusetzen,> weil man es für böse erklärt hat.
Jein. Ich verstehe Deinen Standpunkt, aber ich teile ihn
nicht (vollständig).
Du setzt einen verständigen Programmierer voraus und
betrachtest den konkreten Einzelfall, und unter der Prämisse
verstehe ich Deine Schlussfolgerung.
Allerdings blendest Du zwei Fragen aus:
1. Warum wurde goto "für böse erklärt"?
2. Liegt tatsächlich immer der Fall des verständigen
Programmierers vor, der einen guten Grund für genau
diese "goto" hat?
> Programmierung ist ein kompliziertes Handwerk. Da sind> manchmal auch Werkzeuge sinnvoll, mit denen nur Experten> richtig umgehen können.
Ja.
> Für eine CNC-Fräse muss man auch erstmal lernen, wie man sie> benutzt. Das heißt aber nicht, dass man deshalb alle - auch> die, die den Umgang damit gelernt haben - zwingen sollte,> stattdessen alles mit der Feile zu bearabeiten.
Richtig, nein.
> Den Azubi, der gestern angefangen hat, lässt man aber besser> nicht an die Maschine. Klar, ist ein etwas überzogener> Vergleich, [...]
Neinnein, der ist sehr passend; er zeigt nämlich das Problem:
Die "Feile" der Softwerkerei existiert nicht, denn darunter
würde ich eine Sprache verstehen, die hinsichtlich Portabilität,
Eignung für Systemprogrammierung und Effizienz ungefähr (!)
vergleichbar mit C, aber einfacher zu handhaben ist.
Wenn ich eine ECHTE Alternative zu C hätte, würden mich die
Macken von C nicht interessieren -- aber es gibt ja keine.
(Zumindest kenne ich keine.)
>>> Das hat auch keiner behauptet. Aber umgekehrt sollte man>>> auch nicht alles, was man in der Schule gelernt hat,>>> unreflektiert übernehmen und zum Dogma machen.>>>> Dass das eine handfeste Beleidigung ist, ist Dir bewusst?>> Wo du da eine Beleidigung zu sehen glaubst, vermag ich nicht> zu erkennen.
Man kann das lesen als "Wer nachdenkt, ist sowieso meiner
Meinung, und wer anderer Meinung ist, hat nur nicht selber
nachgedacht, sondern plappert nach, was ihm eingetrichtert
wurde."
> Es war jedenfalls nicht meine Absicht, irgendwen zu beleidigen.
Schon in Ordnung.
>> Und ich darf dabei auch zu anderen Ergebnissen kommen als Du,>> und ich darf diese abweichende Meinung sogar öffentlich>> vertreten.>> Natürlich. Nur habe ich bei den meisten von denen, die goto> vehement ablehnen,
Hmm. Ich lehne es nicht vehement ab.
Ich verstehe nur nicht, warum man Witze über Leute macht, die
es tun.
Ich habe übrigens erst vorhin, anlässlich dieser Diskussion
mal nachgesucht und dabei festgestellt, dass Tcl gar nicht
über "goto" verfügt. Mangels Bedarf wusste ich das bisher
gar nicht. Gibts einfach nicht -- und ich habe es nie vermisst.
Ist Ousterhout ein Ignorant, Depp, Kleingeist,... weil er
goto nicht in Tcl aufgenommen hat?
> nicht den Eindruck, dass das aufgrund selbst gebildeter> Meinung passiert.
Hmm. Wahrscheinlich bin ich voreingenommen.
Ich bin PASCAL-sozialisiert. Als ich vor 25 erstmalig
einen Anlauf versucht habe, C zu lernen, fand ich C einen
riesengroßen Haufen unsinnig komplizierter, unlesbarer
Sch...e.
Und natürlich wurde ich in einschlägigen Diskussionen
"PASCAL vs. C" immer als der ignorante Blödmann hingestellt,
der einfach viel zu dumm ist, die göttlichen Segnungen
von C zu verstehen.
In der Zwischenzeit habe ich Tcl/Tk entdeckt und war damit
lange hochzufrieden; dann kam wieder mehr Pascal in Gestalt
von Free Pascal, nebenbei hatte ich auch Einblick in die
Steuerungsprogrammierung; nicht zu vergessen die Automaten-
theorie, die man an der Uni gehört hatte.
Jetzt unternehme ich (wegen der Mikrocontroller) wieder
einen Anlauf, C zu lernen, und -- TATAA! -- finde es immer
noch eine riesengroße unlesbare Sonderzeichen-Schotterwüste.
Im Unterschied zu früher habe ich jetzt aber ein viel
größeres Hintergrundwissen (nicht zuletzt übrigens dank
dieses Forums) und bin in Diskussionen renitenter.
Ich will hier nicht in die Details gehen, aber ich gewinne
zunehmend die Auffassung, dass die tatsächlichen Stärken
von C (also die Eigenschaften, die C zu der Schlüsselrolle
verholfen haben, die es immer noch hat) relativ wenig mit
den Dingen zu tun haben, die "normale" C-Programmierer so
vehement an "ihrer" Sprache verteidigen.
Etwas boshafter ausgedrück: Der durchschnittliche C-
Programmierer verteidigt C mit all seinen Eigenheiten
nur deshalb, weil er gar nicht im Detail begriffen hat,
was wirklich gut und was wirklich schlecht daran ist ;)
> Possetitjel schrieb:>> Wenn es Fälle gäbe, in denen goto NOTWENDIG, d.h.>> UNVERZICHTBAR ist, dann könnte man ja darüber reden.>> Zwingend notwendig sind nur sehr wenige Sprachfeatures> (auch Brainfuck ist Touring-vollständig).
Auf DAS Argument habe ich die ganze Zeit gewartet :)
> Deshalb muss man ja nicht gleich alles andere abschaffen.
Zum einen: Nicht "alles andere" sondern nur das Überflüssige :)
Zum anderen: Nicht "abschaffen", sondern "nicht in die Sprache
aufnehmen".
Sprachstandards wachsen nicht auf Bäumen, die ab und an
ausgeästet werden müssen -- wenn etwas in der Sprachdefinition
drinsteht, dann hat es da jemand aktiv hineingeschrieben, der
es für einen tollen Einfall gehalten hat.
Es geht mir gar nicht darum, K&R nachträglich, aus dem
sicheren Abstand von 50 Jahren zu kritisieren. Das meine
ich gar nicht.
Es geht mir um genau die andere Richtung: Manche Prioritäten
haben sich im Laufe der Zeit verschoben. Dazu gehört zum
Beispiel, dass die Konstrukte nicht mehr so compilerfreundlich
formuliert sein müssen, wie es damals war, weil die Compiler-
technik weiter ist und die Compiler viel besser optimieren
können. Zahlreiche C-Hacks sind somit überflüssig, weil der
Compiler auch aus der Langform erkennen kann, wie er das in
kurzen und effizienten Maschinencode umformen kann.
Dazu gehört auch, dass die absolute Anzahl Programmierer sehr
viel größer ist als damals und der Quelltext nicht nur zur
Mensch-Maschine-Kommunikation dient, sondern viel stärker zur
Mensch-Mensch-Kommunikation eingesetzt wird, als es früher
der Fall war. Der Sonderzeichen- und Operatorwahn, der in C
ausgelebt wird, ist unter wahrnehmungspsychologischen Aspekt
einfach kontraproduktiv.
Es genügen Grundkenntnisse der Codierungstheorie, um zu
erkennen, dass eine Syntax, die sowohl "a=b" als auch "a==b"
in identischem Kontext zulässt, ein schlechter Einfall ist.
Possetitjel schrieb:> Allerdings blendest Du zwei Fragen aus:> 1. Warum wurde goto "für böse erklärt"?> 2. Liegt tatsächlich immer der Fall des verständigen> Programmierers vor, der einen guten Grund für genau> diese "goto" hat?
Zu 1:
Diese Gegebenheiten, welche zum "böse" geführt haben gibt es in C/C++
überhaupt nicht. Noch nicht mal im Ansatz. Und damit ist das ein totes
Argument.
Zu 2:
In dem Satz steckt ein "immer"!
Und da es auch Idioten und Stümper gibt, wird es eben nicht "immer"
einen Guten Grund geben. Aber das gilt auch für "ALLE" anderen
Sprachmittel, denn mit denen kann man auch Mist bauen.
PS:
Dein heiß geliebtes Pascal (ich mag es auch) hat ebenfalls ein Goto
eingebaut.
Markus F. schrieb:
[100 gotos im bisherigen Leben]
> Tatsächlich war sicher deutlich mehr als die Hälfte> davon kein eigener Code, sondern der Pfusch anderer> Leute, die vor lauter Verschachtelung am Ende vergessen> haben, allokierte Ressourcen frei zu geben. Wenn man> so was reparieren muss, ohne gleich alles neu zu> schreiben (und damit die gesamte Testmaschinerie> anzuwerfen), ist goto Gold wert.
Das ist interessant, dass Du das so schreibst, und die
Verwendung von goto in den Kontext von Verschachtelungen
stellst.
Weiter oben schrieb Rolf, Hilfsvariablen (innerhalb von
Verschachtelungen) seien für ihn nur Krücken, die er
nach Möglichkeit vermeide.
Ich finde das bemerkenswert, weil ich i.d.R.
Verschachtelungen vermeide und ggf. Hilfsvariablen verwende.
(Die automatentheoretische Begründung dafür ist vielleicht
auch keine echte Begründung und ziemlich esoterisch.)
> Was mich stört ist der sture Dogmatismus, der hier> durchscheint.
Naja, was heisst Dogmatismus? Ist Dein Mathelehrer aus dem
Leistungskurs auch dogmatisch, der behauptet hat, JEDE
quadratische Gleichung hätte GENAU zwei Lösungen (die u.U
auch zusammenfallen können)?
Nach meinem (lückenhaften) Kenntnisstand trafen damals, als
die "strukturierte Programmierung" aufkam (die generell auf
goto verzichten will), zwei Dinge aufeinander: Einerseits
die Beobachtung von Dijkstra, dass die Häufigkeit von goto
negativ mit der Codequalität korreliert, und andererseits
die Erkenntnis, dass es auch aus theoretischer Sicht möglich
ist, vollständig auf goto zu verzichten.
Gerade der letzte Punkt ist extrem interessant: Es geht beim
Verzicht auf goto gerade NICHT darum, einfach ein Sprach-
konstrukt der Hochsprache durch ein anderes zu ersetzen, das
letztlich wieder zum selben Maschinencode führt -- sondern
es geht darum, dass man von allen denkbaren Ablaufgraphen
alle aussondern kann, die bestimmten Regeln widersprechen,
und TROTZDEM noch alles berechnen kann, was berechenbar ist.
Dass das nicht nur akademisches Geschwätz ist, sondern auch
in der Praxis funktioniert, wird von Tcl bewiesen; dort gibt
es schlicht kein goto.
Tcl hat sicher zahlreiche Macken und Schwächen, aber
ausgerechnet das Fehlen von goto würde ich nicht dazu
zählen. Man braucht es nicht.
Ich sehe nicht, was daran dogmatisch ist. (Vielleicht eine
Folge von Betriebsblindheit...)
Possetitjel schrieb:
[...]
Du hast aber schon einen Hang zur epischen Breite, oder ;-)
Possetitjel schrieb:> "for" und "Eleganz" ist ein inhärenter Widerspruch. ;)
ceterum censeo, die for-loops in Lisp sind wesentlich eleganter. Aber an
Fortran kommt nix heran
Possetitjel schrieb:> Nach meinem (lückenhaften) Kenntnisstand trafen damals, als> die "strukturierte Programmierung" aufkam (die generell auf> goto verzichten will), zwei Dinge aufeinander: Einerseits> die Beobachtung von Dijkstra, dass die Häufigkeit von goto> negativ mit der Codequalität korreliert, und andererseits> die Erkenntnis, dass es auch aus theoretischer Sicht möglich> ist, vollständig auf goto zu verzichten.
Ach wo. Vielleicht bist du bloß zu jung (kann ja mal passieren..)
Damals hatte ein typischer Homecomputer einen residenten
Basic-Interpreter im ROM - und das war damals da klassische interaktive
Basic: was man ohne Zeilennummer eintippt, wird ausgeführt, was man mit
Zeilennummer eintippt, wird im gerade geladenen Programm gespeichert.
Das war die Zeit, wo man ohne GOTO schlichtweg nicht auskam.
Nochmal zum tief Einsinken: das GOTO war damals in Basic
lebensnotwendig.
Selbst beim ersten IBM-PC war Basic der Anfang von allem, wenn das BIOS
kein BS auf der Floppy fand, wurde schlichtweg ins Microsoftsche Basic
verzweigt. Nun komme bitte keiner mit CP/M, wo es schon am Ende der 70er
keinen residenten Basicinterpreter gab. Diese Gefilde waren damals
unerschwinglich. 16 K RAM hatten damals ein halbes Vermögen gekostet,
von 64 K ganz zuschweigen.
Mit dem Vordringen besser strunturierter Programmiersprachen - im
Klartext Pascal (HISOFT auf dem ZX-Spectrum so um 1984..86 etwa, hab's
nicht auswendig gelernt) kam ein Paradigmenwechsel. Man hatte plötzlich
Prozeduren und Funktionen, die echte Argumente haben konnten und es gab
Syntaxelemente, die zum Strukturieren geeignet waren wie repeat xxx
until yyy; oder do...while.
Das war für alle jungen Burschen, die in Basic sozialisiert waren, etwas
völlig neues und grundanderes! Um das den Leuten einzuprügeln, kamen
Sprüche auf wie "GOTO ist böse" und dergleichen. Das war auch bloß ein
Dogmatismus, wenngleich zum Anstoßen des Umdenkens wohl damals
notwendig.
Das alles hat mit Dijkstra nichts zu tun. Allerdings kann man
beobachten, daß gerade in den Kreisen der C-Leute derartige Dinge wie
Goto oder globale Variablen noch immer ausgesprochen fanatisch
diskutiert werden. Mittlerweile sollte sich doch in solchen Dingen die
Hitzköpfigkeit gelegt haben und der Erkenntnis gewichen sein, daß es in
jeder Programmiersprache, die mit Anweisungen arbeitet, eben auch sowas
wie einen unbedingten Sprung geben soll. Das gehört zur Vollständigkeit
dazu.
W.S.
Michael R. schrieb:> Du hast aber schon einen Hang zur epischen Breite, oder ;-)
Hmpf. Treffer, versenkt!
> Possetitjel schrieb:>> "for" und "Eleganz" ist ein inhärenter Widerspruch. ;)>> ceterum censeo, die for-loops in Lisp sind wesentlich> eleganter.
Nun ja, was ich auf die Schnelle gesehen habe, erinnert
doch stark an "foreach" in Tcl -- und dessen Eleganz
steht ja wohl außer Frage :)
> Aber an Fortran kommt nix heran
Über Geschmack lässt sich nicht streiten...
W.S. schrieb:> Mittlerweile sollte sich doch in solchen Dingen die> Hitzköpfigkeit gelegt [...] haben
Tja... wie man sieht, offensichtlich nicht.
Possetitjel schrieb:>> Aber an Fortran kommt nix heran> Über Geschmack lässt sich nicht streiten...
Aber wenn schon Fortran 66, "to compile loops like god meant them to be"
Nop schrieb:> Possetitjel schrieb:>>> Wenn man ernsthaft darüber diskutieren kann, die Verwendung>> eines formalsprachlich korrekten Konstruktes zu verbieten,>> dann ist die Sprachdefinition schlecht.>> Nein, sondern dann wurde die Sprache eben von Profis entworfen,
"Profis haben die Titanic gebaut, ein Amateur die Arche Noah."
> Wenn ich mir ansehe, wie man in Pascal üblicherweise gestackte> Fehlerbehandlung ohne goto macht,
Über die Pascal-vs.-C-Debatten bin ich 20 Jahre hinaus; das
koche ich nicht wieder auf. Aktuelle Referenz wäre Tcl.
Dort gibt es schlicht kein goto, und ich habe es nie vermisst.
> oder auch Ausstieg aus geschachtelten Schleifen, dann ist> das noch unübersichtlicher. Das läuft dann nämlich auf> tief geschachtelte ifs, Code-Duplikation und/oder absurde> Hilfs-Variablen hinaus.
Das ist bemerkenswert, denn Du bist schon der Dritte, der
goto in den Kontext von Verschachtelungen stellt.
"Tief geschachtelte ifs": Vermeide ich generell; da mache
ich zu viele Fehler (nicht wegen der Syntax, sondern aus
inhaltlichen Gründen). Ich verwende tendenziell lieber
einfache ifs und Hilfsvariablen.
"Code-Duplikationen": Pascal und Tcl kennen glücklicherweise
lokale Prozeduren bzw. Funktionen -- im Gegensatz zu C.
Doppelter Code ist daher i.d.R. unnötig.
Und zum Thema "absurde Hilfsvariablen": Die Absurdität liegt
durchaus im Auge des Betrachters. Es gibt sehr wohl einen
automatentheoretischen Blickwinkel, unter dem die Hilfs-
variablen nicht nur nicht absurd, sondern im Gegenteil
völlig natürlich sind.
> Das goto, worauf sich Dijkstra damals bezogen hat, und> was tatsächlich zu Spaghetti geführt hat, war nämlich> ein gänzlich anderes. Damals konnte man noch anhand> absoluter Zeilennummern
Zeilennummern oder Labels macht keinen grundsätzlichen
Unterschied.
> quer durch das ganze Programm springen.
Das macht auch nur einen graduellen, keinen prinzipiellen
Unterschied. Insofern teile ich Deine Auffassung vom
"gänzlich anderen goto" nicht.
Ich gestehe aber zu, dass die schlimmsten Macken des
klassischen goto in C verboten sind. (Auch graduelle
Unterschiede sind Unterschiede; auch ein gradueller
Fortschritt ist ein Fortschritt. Soweit gehe ich mit.)
> Das hat so gut wie nichts mit C-goto zu tun, was man nur> innerhalb einer Funktion benutzen kann,
Der Teller mit Spaghetti ist etwas kleiner, aber Spaghetti-
code produzieren kann man immer noch. Die Komplexität dessen,
was man in einer Funktion unterbringen kann, ist durch die
Sprache nicht beschränkt.
> Richtig ist aber auch, daß Rückwärtssprünge mit goto> bedenklich sind, auch in C. Das kann man meistens mit> einer while-Schleife umgehen, die einen Zustandsautomaten> enthält. Der ist dann auch übersichtlicher. So mache ich> jedenfalls algorithmische Rückwärtssprünge, sofern ist> nicht das letzte bißchen an Performance gerade an der> Stelle brauche. Schon weil ein Zustandsautomat ein Idiom> ist, was jeder nachfolgende Programmierer kennt und sofort> versteht.
Ich bin beeindruckt. Genau das ist nämlich der Knackpunkt:
Der Zusammenhang zwischen den zugelassenen Sprachkonstrukten
und den (damit) formulierbaren Automatenstrukturen.
Um hier nochmal auf die "absurden Hilfsvariablen" zurück-
zukommen: Das sind einfach die Zustandsvariablen eines
passenden endlichen Automaten.
Und ich persönlich finde es auch schöner, diesen Zuständen
einen Namen zu geben und sie explizit per Anweisung zu
setzen, als sie in der Steuerstruktur des Programmes zu
verstecken. Der zugehörige Automat ist nämlich trotzdem
noch da -- er ist nur nicht so gut zu erkennen.
Das ist aber persönliche Macke, das gebe ich zu.
> Selbst Vorwärtssprünge mit goto sind in den allermeisten> Fällen auf Fehlerbehandlung begrenzt. Computed goto, also> goto anhand eines Label-Arrays per Index, ist leider immer> noch nicht Teil des C-Standards (GCC und Clang können es).> Das kann man aber algorithmisch gut gebrauchen, wenn es> auf Performance ankommt. Sowas betrifft etwa Interpreter,> Python sei genannt.
Jetzt sind wir schon beim anderen Thema: "Switch" verbieten! :)
Markus F. schrieb:> Nicht, weil ich's unbedingt gebraucht hätte, sondern weil es in der> Situation die einfachere, leichter lesbare, einfach bessere Lösung war.
Genau! Das ist genau DER Grund, goto zu benutzen.
In diesem Beispiel, in dem auch noch eine Variable genutzt werden muss:
Beitrag "Re: Lesbarer ProgrammCode"
wäre ein goto angebracht.
Was macht eigentlich break in dem Beispiel? Ist nichts anderes als ein
goto, wenngleich ein eingeschränktes.
Ein goto in solch wenigen Situationen gezielt eingesetzt ist ein gutes
goto.
Wer mit goto Spagetticode erzeugt, hat in der professionellen
Programmierung nicht verloren.
Leider halten sich nicht alle dran ;)
Und nein, ich darf auch kein goto verwenden. Nicht einmal ein break um
eine Schleife zu verlassen. Ernsthaft. Der Rulechecker würde meckern und
ich müsste es ändern wenn ich break/goto verwende. %-o =Vor die Stirn
klatsch=
Ich nutze dann Steuervariablen wie in dem aufgeführten Beispiel gezeigt.
Ich finde es wirklich dummes Zeug.
900ss D. schrieb:> Markus F. schrieb:>> Nicht, weil ich's unbedingt gebraucht hätte, sondern weil>> es in der Situation die einfachere, leichter lesbare,>> einfach bessere Lösung war.>> Genau! Das ist genau DER Grund, goto zu benutzen.
Es ging (mir) doch gar nicht darum, dass manchmal wirklich
gute Gründe gibt, goto zu verwenden.
Es ging (mir) um die Frage, ob Menschen, die goto verbieten,
in jedem Falle dogmatisch, beschränkt, kleingeistig, ... sind,
oder ob es vielleicht auch GUTE Gründe dafür gibt.
Klassischer Fall einer Güterabwägung: Ist das, was man durch
das Verbot gewinnt, wichtiger als das, was man verliert?
> Was macht eigentlich break in dem Beispiel? Ist nichts> anderes als ein goto, wenngleich ein eingeschränktes.
Die Einschränkung ist aber gerade das, worum es geht!
Mit break kann man z.B. nicht rückwärts springen -- mit
goto dagegen kann man eine parasitäre Schleife basteln.
> Und nein, ich darf auch kein goto verwenden. Nicht einmal> ein break um eine Schleife zu verlassen. Ernsthaft.
Kein break?! Warum das denn?
Possetitjel schrieb:> goto dagegen kann man eine parasitäre Schleife basteln.
Genau das kann man ja am Basteltisch machen wer möchte. In
professionellem Code hat das nichts zusuchen. goto gezielt in wenigen
sinnvollen Stellen einsetzen ist ok.
Possetitjel schrieb:> Kein break?! Warum das denn?
Keine Ahnung, begründet würde keine Regel. Es gibt noch mehr so Blödsinn
in dem Regelwerk.
900ss D. schrieb:> Possetitjel schrieb:>> goto dagegen kann man eine parasitäre Schleife basteln.>> Genau das kann man ja am Basteltisch machen wer möchte.
???
Niemand MÖCHTE einen Fehler machen -- aber trotzdem werden
dauernd welche gemacht!
> In professionellem Code hat das nichts zusuchen.
Wenn EIN goto erlaubt ist, um aus geschachtelten Schleifen
herauszuspringen, dann sind auch ZWEI gotos zulässig, um
aus zwei (unterschiedlichen, unabhängigen) Blöcken
geschachtelter Schleifen herauszuspringen.
Jetzt musst Du nur noch die Labels verwechseln, und die
ungewollte Schleife ist fertig.
> Possetitjel schrieb:>> Kein break?! Warum das denn?>> Keine Ahnung, begründet würde keine Regel. Es gibt noch> mehr so Blödsinn in dem Regelwerk.
Was ich wissen wollte: Welches Regelwerk ist es denn?
MISRA wohl nicht?!
900ss D. schrieb:> Possetitjel schrieb:>> Kein break?! Warum das denn?>> Keine Ahnung, begründet würde keine Regel. Es gibt noch mehr so Blödsinn> in dem Regelwerk.
Das mit einem Einstiegpunkt und einem Ausstiegpunkt gilt ja auch für
Schleifen ;-)
"for" soll verwendet werden für eine feste Anzahl an Durchläufen -->
break hier unsinnig
"while" oder "do while" sind bedingte Schleifen, bei dem der Ausstieg
schon in der while steht --> auch kein break erforderlich
Mit ein paar breaks drin wird sowas sehr schnell unstrukturiert. So hat
man die Gewissheit, dass die Schleife ganz oder gar nicht abläuft.
"switch case" sind vielleicht auch verboten? Oder halt mit der Regel
immer ein break pro case? Macht ja manchmal Sinn den break an einer
Stelle wegzulassen, was aber auch ein wilden Sprung gleicht. Stattdessen
könnte man da ja wirklich zum Goto greifen, damit das sofort auffällt
;-)
Arduino F. schrieb:> Diese Gegebenheiten, welche zum "böse" geführt haben
Also, vielleicht muss ich doch mal was klarstellen. Mir
hat niemals irgend jemand erzählt, goto sei "böse".
Ich habe gelernt, dass
1. Spaghetticode durch übermäßige Verwendung von goto
entsteht;
2. "strukturierte Programmierung" ohne goto auskommt
und sich auf die drei Elemente
- Sequenz,
- Verzweigung und
- Schleife
beschränkt;
3. durch theoretische Betrachtungen gesichert ist, dass
man in jedem Falle auch mit den genannten drei Elementen
auskommt, goto also im Prinzip nie wirklich benötigt.
> gibt es in C/C++ überhaupt nicht. Noch nicht mal im Ansatz.
Das stimmt NUR dann, wenn das Sprungziel ("Label") stets nur
NACH der goto-Anweisung stehen darf.
Ist das so?
> Zu 2:> In dem Satz steckt ein "immer"!> Und da es auch Idioten und Stümper gibt,
Nicht nur.
Es gibt auch Anfänger, denen eine Aufgabe aufgedrückt wird,
die sie völlig überfordert, Programmierer, die halb zwei in
der Nacht vor der Auslieferung noch die Kastanien aus dem
Feuer holen sollen, oder Programmierer, die in einem Team,
in dem es niemand länger als ein halbes Jahr aushält, zu
einem brauchbaren Ergebnis kommen wollen.
Die Welt ist nicht so einfach, wie Du sie gern hättest.
> wird es eben nicht "immer" einen Guten Grund geben. Aber> das gilt auch für "ALLE" anderen Sprachmittel, denn mit> denen kann man auch Mist bauen.
Das ist im Prinzip richtig.
Die entscheidenden Fragen sind nur: Wie groß ist der Mist,
den man baut, und wie schnell fällt er auf?
Das Problem an goto ist, dass man damit (im Gegensatz zu
den anderen Steueranweisungen) die Ablaufstruktur beliebig
kaputtmachen kann. Goto ist zuviel Macht in einer einzelnen
Anweisung.
> PS:> Dein heiß geliebtes Pascal (ich mag es auch)
Die Stichelei ist unnötig. Pascal hat andere Macken als C,
aber sicher genauso viele.
> hat ebenfalls ein Goto eingebaut.
Sicher -- und ich frage mich ernsthaft, warum eigentlich.
Tcl hat übrigens kein goto :)
Possetitjel schrieb:> goto also im Prinzip nie wirklich benötigt.
Im Prinzip nie, man kann schließlich auch mit der Kirche ums Dorf.
Was m.E. in der Diskussion bisher nicht berüksichtigt wurde, ist, dass
ein (C-)Code auch das Compilat einer anderen Sprache bzw. eines
Programms sein kann. Und damit nicht die Lesbarkeit im Vordergrund
steht.
Z.B. bei der Codegenerierung von einer graphischen UML-Programmierung.
Die Pfeile in einem UML-Diagramm sind ja letztlich Gotos. Das mit
Funktionen, IF-Abfragen, EXITs, BREAKS etc. zu emulieren kann die
Codegenerierung deutlich komplizierter machen.
Damit ist auch klar, dass solche Konstrukte für Universalsprachen wie C
oder Pascal eben unverzichtbar sind.
Possetitjel schrieb:> Die Welt ist nicht so einfach, wie Du sie gern hättest.
Ach? Nein?
> Goto gehört abgeschafft.
Wer will denn hier die Menschheit (zumindest die Programmierer) in ein
Korsett zu pressen?
Ja, ich stimme dir zu:
Die Welt ist nicht so einfach, wie Du sie gern hättest.
Es gibt Code, welcher sich mit Gotos einfacher strukturieren lässt, als
mit zwanghafter Goto Vermeidung. Das wurde hier schon mehrfach genannt.
Selbst du hast da zugestimmt.
Alte Regel:
Hat man 2 mögliche (fehlerfreie) Varianten, dann wählte man die
einfachere und übersichtlichere.
Im Klartext:
Du möchtest, ausschließlich aus Dogmatismus, einen höheren/unnützen
Komplexitätsgrad erzwingen.
Possetitjel schrieb:> oder Programmierer, die in einem Team,> in dem es niemand länger als ein halbes Jahr aushält, zu> einem brauchbaren Ergebnis kommen wollen.
Ich kann nur froh sein, dass sich in meinem Arbeitsumfeld nicht solche
"Priester des Absoluten", solche Dogmatiker, wie du befinden.
Und ich kann auch nur jedem anderen wünschen, dass er nicht so einen wie
dich als Vorgesetzten vor die Nase gesetzt bekommt.
Denn sonst ist man fix bei:
> einem Team, in dem es niemand länger als ein halbes Jahr aushält
So...
Und damit ist das Goto Thema,jetzt und hier, für mich durch.
Possetitjel schrieb:> Wenn man ernsthaft darüber diskutieren kann, die Verwendung> eines formalsprachlich korrekten Konstruktes zu verbieten,> dann ist die Sprachdefinition schlecht.
In diesem Falle: nein, denn die Diskussion hier hat die "Lesbarkeit" des
Codes als Horizont.
Es gibt jedoch auch Fälle, wo die Lesbarkeit schlicht keine Rolle
spielt, nämlich bei auto-generiertem Code, und viele der Leser hier
verwenden tatsächlich solchen Code, auch wenn ihnen das nicht klar ist
[*].
Die Folgerung
Lesbarkeit => Kein goto => goto ist überflüssig => goto verbannen
bricht also bereits unter der nicht immer erfüllten Annahme zusammen,
dass Lesbarkeit immer eine Rolle spiele.
[*] Ein Beispiel ist GCC, der aus der Maschinenbeschreibung u.a. C/C++
Code erzeugt, um bestimmte Bäume möglichst schnell zu durchsuchen. An
jedem Knoten sind andere Entscheidungen zu treffen, und während des
Traversierens werden Eigenschaften des gewählen Pfades eingesammelt,
vergleichbar mit Capturing bei regulären Ausdrücken.
In diesem Fall zählt:
1) An erster Stelle Host-Performance, also die Zeit, die GCC selbst zum
Compilieren braucht. Üblicherweise werden solche auto-generierten Teile
genauen Benchmarks unterzogen, um beste Host-Performance zu erhalten,
und die gewählte Expansion daran angepasst.
2) An zweiter Stelle Wartbarkeit, Nachvollziehbarkeit und Lesbarkeit des
Generators.
3) Erst an dritter Stelle die Lesbarleit des generierten Code. Normal
liest schlichtweg niemand diesen Code.
> Und genau das ist auch meine (Außenseiter-)Meinung.
Wer keine Ahnung hat bildet sich stattdessen eine Meinung ;-/
> Da man aber i.d.R. nicht die Macht hat, das Übel an der> Wurzel zu packen, beschränkt man sich auf die Symptom-> behandlung und verbietet eben die Verwendung von goto.
Es gibt eben auch Nischen, wo goto sinnvoll ist; wie im gezeigten
Beispiel.
Dass diese Nischen jenseits des Horizonts "normaler" Anwender sind, ist
nicht verwunderlich; aber dadurch verschwindet nicht die Berechtigung in
der Nische.
Der angehängte Code ist von einem avr-gcc, Backends wie x86, arm oder
powerpc erzeugen noch wesentlich größere Bäume.
Hier mal ein Beispiel, wie goto die Les- und Wartbarkeit erhoeht:
1
intfancy_device_driver(void)
2
{
3
uint8_t*mem_1;
4
uint16_t*mem_2;
5
uint32_t*mem_3;
6
7
intret_val=0;
8
9
10
mem_1=malloc(10);
11
if(mem_1==NULL){
12
ret_val=-1;
13
14
gotomem_1_alloc_fail;
15
}
16
17
/* do fancy stuff */
18
19
mem_2=malloc(23*sizeof(uint16_t));
20
if(mem_2==NULL){
21
ret_val=-2;
22
23
gotomem_2_alloc_fail;
24
}
25
26
/* do fancy stuff */
27
28
mem_3=malloc(47*sizeof(uint32_t));
29
if(mem_3==NULL){
30
ret_val=-3;
31
32
gotomem_3_alloc_fail;
33
}
34
35
/* do fancy stuff */
36
37
38
free(mem_3);
39
40
mem_3_alloc_fail:
41
free(mem_2);
42
43
mem_2_alloc_fail:
44
free(mem_1);
45
46
mem_1_alloc_fail:
47
returnret_val;
48
}
Jetzt moege mir doch bitte einer von denen, die nach einem Verbot/der
Ausmerzung von goto bruellen, zeigen, wie sie das ohne goto auch nur
ansatzweise so sauber hinbekommen. Und dann schaut auch mal was mit
eurem Code passiert, wenn ihr noch einen oder zwei neue Speicherbloecke
allokiert. Ohne goto explodiert der Code und es entsteht viel doppelter
Code um den Speicher wieder freizugeben (je speicher 2x free: 1x fuer
den Fehlerfall, und 1x fuer den Fall das alles geklappt hat). Mit goto
braucht man nur 1x free pro Speicher, egal ob Fehler oder nicht.
Markus F. schrieb:> Possetitjel schrieb:>> Tcl hat übrigens kein goto :)>> Tcl ist auch keine systemnahe,
Das stimmt.
> hochoptimierende Programmiersprache.
Das stimmt ziemlich sicher nicht. Die Performance von
Tcl ist nicht so schlecht, wie häufig behauptet wird.
> Tcl ist ein Plastiklöffel.
Was soll das?
Arduino F. schrieb:> Possetitjel schrieb:>> Die Welt ist nicht so einfach, wie Du sie gern hättest.> Ach? Nein?
Nein.
>> Goto gehört abgeschafft.
Na jetzt geht's aber los. Zitate fälschen ist -- im Gegensatz
zu goto -- aber WIRKLICH böse. Den hier "zitierten" Satz habe
ich nicht geschrieben.
> Wer will denn hier die Menschheit (zumindest die> Programmierer) in ein Korsett zu pressen?
Ich nicht. Ich habe nur die Frage aufgeworfen, wieso Witze
über die Leute gemacht werden, die in ihrem Wirkungsbereich
goto verbieten.
> Es gibt Code, welcher sich mit Gotos einfacher strukturieren> lässt, als mit zwanghafter Goto Vermeidung. Das wurde hier> schon mehrfach genannt.> Selbst du hast da zugestimmt.
Ja, dabei bleibe ich auch.
> Alte Regel:> Hat man 2 mögliche (fehlerfreie) Varianten, dann wählte man> die einfachere und übersichtlichere.
Ja. Wenn man diese Wahl hat, dann wählt man so.
> Im Klartext:> Du möchtest, ausschließlich aus Dogmatismus, einen> höheren/unnützen Komplexitätsgrad erzwingen.
Nein.
Es geht nicht um Dogmatismus, sondern um eine klassische
Güterabwägung: Was gewinnt man, wenn man goto verbietet,
und was verliert man?
Was man beim goto-Verbot verliert, darüber besteht weitgehend
Einigkeit. Ich vermisse eine faire Diskussion dessen, was man
gewinnt.
Auf meine Bemerkungen dazu wurde bisher nicht sachlich
geantwortet.
Possetitjel schrieb:> Markus F. schrieb:>>> Possetitjel schrieb:>>> Tcl hat übrigens kein goto :)>>>> Tcl ist auch keine systemnahe,>> Das stimmt.>>>> hochoptimierende Programmiersprache.>> Das stimmt ziemlich sicher nicht. Die Performance von> Tcl ist nicht so schlecht, wie häufig behauptet wird.>
Die Performance von Tcl ist gegenüber einem optimierten C-Programm
miserabel (nach meinen Versuchen nicht nur Faktor 2 oder so, sondern
eher 200 bis 2000). Das soll nicht heissen, dass man es nicht gebrauchen
kann. Man kann es gebrauchen, aber nicht für alles.
>>> Tcl ist ein Plastiklöffel.>> Was soll das?
Wenn Du meinen Beitrag oben gelesen hättest, würdest Du das verstehen.
Kaj G. schrieb:> Jetzt moege mir doch bitte einer von denen, die nach einem Verbot/der> Ausmerzung von goto bruellen, zeigen, wie sie das ohne goto auch nur> ansatzweise so sauber hinbekommen.
In anderen Sprachen mit Exceptions. ;-)
Anmerkung: auch, wenn ich diese Antwort geschrieben habe, bin ich
keiner, der „nach einem Verbot von goto brüllen“ würde. :)
Kaj G. schrieb:> Jetzt moege mir doch bitte einer von denen, die nach einem Verbot/der> Ausmerzung von goto bruellen, zeigen, wie sie das ohne goto auch nur> ansatzweise so sauber hinbekommen.
Ich brülle zwar nicht und verwende auch kein C, ich versuche es aber
trotzdem mal ;-) :
Das "checked_free" brauchst du nicht, es ist legal, free() einen
Nullzeiger zu übergeben.
Aber: du deallozierst jetzt immer alles. :-)
Wenn schon, dann
1
if(mem_1==NULL||mem_2==NULL||mem_3==NULL)
2
{
3
free(mem_1);
4
free(mem_2);
5
free(mem_3);
6
return-42;
7
}
Gut, der war noch einfach. :-) Es gibt kompliziertere Fälle, bei
denen man dann wirklich sackweise Hilfsfunktionen machen müsste.
Im Sinne der „reinen Lehre“ wäre ja auch ein vorzeitiges „return“
nur ein verkapptes „goto“ und damit strikt zu vermeiden …
Torsten R. schrieb:> ich versuche es aber> trotzdem mal ;-) :Torsten R. schrieb:> uint8_t *mem_1 = malloc(10);> /* do fancy stuff */
klappt schon auf dem Papier nicht
wenn malloc(10) erfolglos war kann
Torsten R. schrieb:> /* do fancy stuff */
nicht vernünftiges mehr machen falls
> /* do fancy stuff */
den mem brauchte!
Jörg W. schrieb:> Das "checked_free" brauchst du nicht, es ist legal, free() einen> Nullzeiger zu übergeben.
Ah, ok. Ich dachte, das gilt nur für C++ delete.
> Aber: du deallozierst jetzt immer alles. :-)
Ja, dass macht das Original aber auch.
Hier die C++ Variante:
Johann L. schrieb:> Possetitjel schrieb:>> Wenn man ernsthaft darüber diskutieren kann, die Verwendung>> eines formalsprachlich korrekten Konstruktes zu verbieten,>> dann ist die Sprachdefinition schlecht.>> In diesem Falle: nein, denn die Diskussion hier hat die> "Lesbarkeit" des Codes als Horizont.>> Es gibt jedoch auch Fälle, wo die Lesbarkeit schlicht keine> Rolle spielt, nämlich bei auto-generiertem Code,
Okay.
Das ist, wenn ich Dich richtig verstehe, ein (zweites) Argument
dafür, dass man goto sowieso nicht aus dem Standard streichen
könnte -- eben weil man goto für automatisch generierten C-Code
haben will.
Das stärkt aber die Position der Leute, die die Verwendung von
goto durch Menschen per Arbeitsanweisung verbieten. Schließlich
geht es gar nicht darum, dass goto für die MASCHINE irgendwie
schädliche wäre -- sondern nur darum, dass der programmierende
MENSCH zuviel Quatsch mit dieser Anweisung anstellen kann.
Also verbietet man es dem Menschen und erlaubt es der Maschine.
>> Und genau das ist auch meine (Außenseiter-)Meinung.>> Wer keine Ahnung hat bildet sich stattdessen eine Meinung ;-/
Tja... mühsam ernährt sich das Eichhörnchen von den Früchten
des Waldes...:)
>> Da man aber i.d.R. nicht die Macht hat, das Übel an der>> Wurzel zu packen, beschränkt man sich auf die Symptom->> behandlung und verbietet eben die Verwendung von goto.>> Es gibt eben auch Nischen, wo goto sinnvoll ist; wie im> gezeigten Beispiel.
Natürlich -- das habe ich ja nie bestritten.
> Dass diese Nischen jenseits des Horizonts "normaler"> Anwender sind, ist nicht verwunderlich; aber dadurch> verschwindet nicht die Berechtigung in der Nische.
Naja, das erinnert doch stark an "Spinat wird sehr schmackhaft,
wenn man ihn kurz vor dem Verzehr durch ein saftiges Schnitzel
ersetzt." :)
Es sind ja gerade die "normalen" Anwender, die hier das Verbot
von goto anprangern.
Auf der rein persönlichen Ebene verstehe ich die Verärgerung
auch; es ist halt zum Kotzen, wenn man aufgrund einer dämlichen
Festlegung ein lt. Standard legitimes und im konkreten Falle
auch angemessenes Konstrukt nicht einsetzen darf.
Die Argumentationslinie gibt ja durchaus Sinn: Die Sachlage
in C heute ist mit derjenigen zur Entstehungszeit von
"Go To statement considered harmfull" nicht vergleichbar,
weil:
1. in C zahlreiche Steueranweisungen existieren, die den
Prinzipien der strukturierten Programmierung gehorchen,
und diese i.d.R. von vernünftigen Programmierern auch
eingesetzt werden;
2. das Missbrauchspotenzial von goto durch Beschränkung auf
die aktuelle Funktion ohnehin eingeschränkt ist;
3. der Verzicht auf goto kontraproduktiv sein kann, weil
Verwenden von goto die Lesbarkeit verbessern würde.
Dennoch bleibt für mich als Fazit: Die Apokalypse tritt
sicher nicht ein, wenn man goto verwendet -- aber sie tritt
genausowenig ein, wenn man die Verwendung durch Menschen
verbietet.
Jörg W. schrieb:> Das "checked_free" brauchst du nicht, es ist legal, free() einen> Nullzeiger zu übergeben.
Das ist zwar richtig, aber die (theoretischen) betrachtungen zu solchen
Fällen gehen meist von "allokierbaren Ressourcen" aus, und das muss
nicht immer Speicher (und daher nicht immer malloc()/free() sein. oft
sind es auch (beliebige) Handles, und oft auch "aufeinander aufbauend",
d.h. obigem zweiten malloc() wird ein Parameter aus dem ersten malloc()
mitgegeben.
Ja, natürlich, das geht alles mit beliebig tief verschachtelten
if-Schlei^H^H^H^H^H^H Bedingungen , aber lesbar ist das nicht mehr...
Jörg W. schrieb:> Im Sinne der „reinen Lehre“ wäre ja auch ein vorzeitiges „return“> nur ein verkapptes „goto“ und damit strikt zu vermeiden
genau! :-)
aber ich liebe "early returns". Vor allem in Kombination der
"umgedrehten" (Perl-) Syntax "do_something if(condition)" und meinem
geliebten "unless()"
Vor vielen, vielen Jahren habe ich ein Programm in PIC- Assembler
geschrieben.
Ein Kollege von mir, ein promovierter Physiker, hat sich einmal
das Listing angesehen und gemeint: GOTO sollte man doch nicht verwenden.
Manche Leute müssen wirklich immer ihre 2 Cent dazugeben.
Das waren meine 2 Cent;-)
R. M. schrieb:> Ein Kollege von mir, ein promovierter Physiker, hat sich einmal> das Listing angesehen und gemeint: GOTO sollte man doch nicht verwenden.
Kommt FORTRAN denn inzwischen ohne GOTO aus? :-)
früher (tm) gabs nur goto um einigermassen strukturiert zu programmieren
auf dem CBM.
Heute versuche ich auch es immer wieder zu vermeiden weil es keine
klaren Ausgänge gibt in Schleifen, man kann einfach raushüpfen und ein
ziemliches Chaos hinterlassen, aber das geht mit Funktionsaufrufe wo
while(1); drin steht genauso.
Zu debuggen ist das schwerer weil irgendwo der µC oder Compi stehen
bleibt.
Auch statt wie hier goto zu meiden macht es mit tief verschachtelte IF
Abfragen nicht besser, ich hatte es versucht sah aber ein das es sinnlos
wird und immer schlechter lesbar.
Jörg W. schrieb:> Kommt FORTRAN denn inzwischen ohne GOTO aus? :-)
Das wäre eine gute Gegenfrage gewesen.
Leider fällt mir so was immer viel zu spät ein.
In diesem Fall Jahrzehnte zu spät ;-)
Kaj G. schrieb:> Jetzt moege mir doch bitte einer von denen, die nach> einem Verbot/der Ausmerzung von goto bruellen,
Tut hier niemand.
> zeigen, wie sie das ohne goto auch nur ansatzweise so> sauber hinbekommen.
Man verwendet in jedem Block zusätzliche Tests auf
ret_val == 0.
Das ist genau die Lösung mit den "abstrusen Hilfsvariablen",
von der weiter oben die Rede war. Und SO extrem abstrus kann
die Hilfsvariable nicht sein, wenn Du sie in Deiner Lösung
ohnehin benötigst.
Das Freigeben des Speichers muss man natürlich umformulieren.
> Und dann schaut auch mal was mit eurem Code passiert, wenn> ihr noch einen oder zwei neue Speicherbloecke allokiert.
Da passiert gar nichts.
Das ist doch im Prinzip nur das klassische Pattern-Action-
Schema.
> Ohne goto explodiert der Code und es entsteht viel doppelter> Code um den Speicher wieder freizugeben
Weder - noch.
Es entsteht nur ein geringfügiger Laufzeitnachteil, weil,
wenn eine Aktion fehlgeschlagen ist, immer noch bei allen
folgenden auf ret_val == 0 getesten und dann zum nächsten
Block gesprungen wird.
Das ist aber nur ein LAUFZEITNACHTEIL und hat nichts mit
der Lesbarkeit zu tun.
Markus F. schrieb:> Possetitjel schrieb:>> Markus F. schrieb:>>>>> hochoptimierende Programmiersprache.>>>> Das stimmt ziemlich sicher nicht. Die Performance von>> Tcl ist nicht so schlecht, wie häufig behauptet wird.>>>> Die Performance von Tcl ist gegenüber einem optimierten> C-Programm miserabel
Mein "nicht so schlecht, wie häufig behauptet wird"
bezog sich natürlich auf den Vergleich mit anderen
Scriptsprachen.
Der Vergleich "optimiertes C" gegen Scriptsprache ist
weitgehend sinnfrei.
> (nach meinen Versuchen nicht nur Faktor 2 oder so,> sondern eher 200 bis 2000).
Und das liegt jetzt daran, dass Tcl kein "goto" kennt?
Ich sehe nicht, worauf Du hinauswillst.
>>> Tcl ist ein Plastiklöffel.>>>> Was soll das?>> Wenn Du meinen Beitrag oben gelesen hättest, würdest Du> das verstehen.
Ich lese alle Beiträge -- und insonderheit die, auf die ich
antworte --, aber ich verstehe trotzdem nicht, was Du meinst.
Hilf mir auf die Sprünge.
Possetitjel schrieb:> Jetzt musst Du nur noch die Labels verwechseln, und die> ungewollte Schleife ist fertig.
Das ist ein Programmierfehler, den man dann behebt. Darum geht es aber
doch garnicht hier. Programmierfehler kannst du mit jedem
Sprachkonstrukt machen.
Possetitjel schrieb:> Was ich wissen wollte: Welches Regelwerk ist es denn?
Hausintern, abgeleitet von Kundenanforderungen.
Da das hier nun bereits die x-te Diskussion zum Thema Goto ist (x≥10),
möchte ich einmal eine ganz banale Frage in den Raum stellen:
Wann habt ihr zum letzten Mal Quellcode in C, Pascal oder irgendeiner
anderen Programmiersprache mit strukturierenden Sprachelementen gesehen,
der Gotos in einer Art und Weise verwendet, die tatsächlich an die
berühmten italienischen Nudeln erinnert?
Bei mir ist das geschätzte 30 Jahre her. Damals und in den Jahren davor
wollten viele Leute vom Basic auf ihrem Heimcomuter (Commodore, Apple,
Atari und wie sie alle hießen) auf modernere Sprachen wie Pascal und C
umsteigen, wussten aber zunächst mit den neu hinzugekommenen Features
wie If-Then-Else, For-/While-Schleifen und Funktionen/Prozeduren mit
Argumentlisten nicht viel anzufangen. Entsprechend gruselig und Basic-
ähnlich sahen ihre Programme aus.
Die in der Folge stattfindende Brandmarkung des Goto an praktisch allen
(Hoch-)Schulen und sonstigen Lehrstätten hat ihre Wirkung aber nicht
verfehlt: Seit den 90er Jahren verwenden Anfänger das Goto praktisch
überhaupt nicht mehr, weil es ihnen genau so eingeprügelt wurde, und die
Fortgeschrittenen verwenden es nur selten und dann mehr oder weniger
begründet. Das ist zumindest meine Beobachtung.
Muss man also die Diskussion um das Für und Wider von Goto immer wieder
von Neuem beginnen, oder hat sich das Problem Wirklichkeit schon längst
erledigt?
Ich meine, letzteres ist der Fall.
Nop schrieb:> Zudem haben 95.34% der Leute, die goto wegen Dijkstras legendärem "goto> considered harmful"-Papers verreißen, den Aufsatz überhaupt nicht> begriffen, sondern plappern nur nach, was sie irgendwo aufgeschnappt> haben.
Die meisten wissen auch nicht, dass der reißerische Titel des Artikels
gar nicht von Dijkstra selbst, sondern von Wirth stammt (der ein paar
Jahre später witzigerweise das Goto in sein Pascal eingebaut hat :)).
Der ursprüngliche Titel lautete "A Case Against the Goto Statement".
Yalu X. schrieb:> Wann habt ihr zum letzten Mal Quellcode in C, Pascal oder irgendeiner> anderen Programmiersprache mit strukturierenden Sprachelementen gesehen,> der Gotos in einer Art und Weise verwendet, die tatsächlich an die> berühmten italienischen Nudeln erinnert?
Du meinst mich?
Dann: Noch NIE!
Damals in (uralt) Basic, ja.(aber das war ja nicht die Frage)
Aber danach nie wieder.
Und wenn ich mich frage, wie oft ich Goto einsetze, dann würde ich das
auf durchschnittlich 1 bis 2 mal im Jahr schätzen.
Höchstens.
Yalu X. schrieb:> Wann habt ihr zum letzten Mal Quellcode in C, Pascal oder irgendeiner> anderen Programmiersprache mit strukturierenden Sprachelementen gesehen,> der Gotos in einer Art und Weise verwendet, die tatsächlich an die> berühmten italienischen Nudeln erinnert?
Ergänzend dazu hier ein Auszug aus dem C++ Style Guide von Google:
https://google.github.io/styleguide/cppguide.html
"Style rules should pull their weight
The benefit of a style rule must be large enough to justify asking
all of our engineers to remember it. The benefit is measured relative to
the codebase we would get without the rule, so a rule against a very
harmful practice may still have a small benefit if people are unlikely
to do it anyway. This principle mostly explains the rules we don’t have,
rather than the rules we do: for example, goto contravenes many of the
following principles, but is already vanishingly rare, so the Style
Guide doesn’t discuss it."
Die Nutzung von Goto wird darin also explizit nicht geregelt. Die
Nutzung von Goto wird zwar durchaus als nicht unkritisch gesehen ("goto
contravenes many of the following principles"). Aber gleichzeitig tritt
es so selten in deren Code auf ("already vanishingly rare") dass es
nicht Wert ist, sich dafür eine Regel merken zu müssen.
Arduino F. schrieb:> Und wenn ich mich frage, wie oft ich Goto einsetze, dann würde ich das> auf durchschnittlich 1 bis 2 mal im Jahr schätzen.> Höchstens.
Wieviele Programme schreibst Du denn im Jahr?
1-2 höchstens?
:)
MfG Paul
Jörg W. schrieb:> In anderen Sprachen mit Exceptions. ;-)
Wenn man Exceptions zur Verfuegung hat, dann geht das damit durchaus
schoener, ja. Hat man in C aber nicht :o)
Torsten R. schrieb:> ich versuche es aber trotzdem mal ;-)
Netter Versuch. Das malloc moeglicherweise fehlschlaegt wurde ja schon
genannt. :-)
Torsten R. schrieb:> Ja, dass macht das Original aber auch.
Nein. Es wird nur der Speicher freigegeben, der auch wirklich allokiert
wurde. Deswegen muessen in meinem Beispiel die Pointer auch nicht mit
NULL initialisiert werden. Entweder hat die Allokation funktioniert,
dann zeigt der Pointer auf eine gueltige Adresse, oder es hat nicht
Funktioniert, dann ist er NULL. Wobei das an der Stelle auch egal ist,
da nur die Speicher freigegeben werden, bei denen die Allokation
erfolgreich war.
Possetitjel schrieb:> Das ist aber nur ein LAUFZEITNACHTEIL und hat nichts mit> der Lesbarkeit zu tun.
Doch, das hat sehr wohl was mit der Les- und Wartbarkeit zu tun.
Beispiel:
1
intbar(void)
2
{
3
uint8_t*mem_1;
4
uint16_t*mem_2;
5
uint32_t*mem_3;
6
7
8
mem_1=malloc(10);
9
if(mem_1==NULL){
10
return-1;
11
}
12
13
/* do fancy stuff */
14
15
mem_2=malloc(23*sizeof(uint16_t));
16
if(mem_2==NULL){
17
free(mem_1);
18
19
return-2;
20
}
21
22
/* do fancy stuff */
23
24
mem_3=malloc(47*sizeof(uint32_t));
25
if(mem_3==NULL){
26
free(mem_2);
27
free(mem_1);
28
29
return-3;
30
}
31
32
/* do fancy stuff */
33
34
free(mem_3);
35
free(mem_2);
36
free(mem_1);
37
38
return0;
39
}
Und jetzt kloppen wir da mal noch 2 Zeiger rein:
1
intbar(void)
2
{
3
uint8_t*mem_1;
4
uint16_t*mem_2;
5
uint32_t*mem_3;
6
...*mem_4;
7
...*mem_5;
8
9
10
mem_1=malloc(10);
11
if(mem_1==NULL){
12
return-1;
13
}
14
15
/* do fancy stuff */
16
17
mem_2=malloc(23*sizeof(uint16_t));
18
if(mem_2==NULL){
19
free(mem_1);
20
21
return-2;
22
}
23
24
/* do fancy stuff */
25
26
mem_3=malloc(47*sizeof(uint32_t));
27
if(mem_3==NULL){
28
free(mem_2);
29
free(mem_1);
30
31
return-3;
32
}
33
34
/* do fancy stuff */
35
36
mem_4=malloc(...);
37
if(mem_4==NULL){
38
free(mem_3);
39
free(mem_2);
40
free(mem_1);
41
42
return-4;
43
}
44
45
/* do fancy stuff */
46
47
mem_5=malloc(...);
48
if(mem_5==NULL){
49
free(mem_4);
50
free(mem_3);
51
free(mem_2);
52
free(mem_1);
53
54
return-5;
55
}
56
57
/* do fancy stuff */
58
59
60
free(mem_5);
61
free(mem_4);
62
free(mem_3);
63
free(mem_2);
64
free(mem_1);
65
66
return0;
67
}
15x free, mit goto waeren es nur 5x free. Das finde ich schon deutlich
unleserlicher als mit goto und es enthaelt sehr viel doppelten Code.
Possetitjel schrieb:> Das Freigeben des Speichers muss man natürlich umformulieren.
Und wie? Wenn eine allokation fehlschlaegt kann die Funktion nicht
weiter machen. Also muss an jeder Stelle wo Speicher allokiert wird,
alle vorherigen, bereits erfolgreich allokierten Speicher, wieder
freigegeben werden. Da helfen auch Hilfsvariablen nichts. Das kannst du
an der Stelle umgehen, wenn man aus den ganzen if eine haessliche
if-else-Kette macht (siehe unten).
Ich gebe aber auch zu, dass das Beispiel anfaengt sehr stark zu hinken,
je mehr Zeiger/malloc man da jetzt in dieser einen Funktion hat.
So, ein letztes, hinkendes Beispiel hab ich noch :P
1
intfoobar(void)
2
{
3
...*mem_1=NULL;
4
...*mem_2=NULL;
5
...*mem_3=NULL;
6
...*mem_4=NULL;
7
...*mem_5=NULL;
8
9
...ret_val=0;
10
11
12
mem_1=malloc(...);
13
if(mem_1==NULL){
14
ret_val=-1;
15
}else{
16
/* ... */
17
18
mem_2=malloc(...);
19
if(mem_2==NULL){
20
ret_val=-2;
21
}else{
22
/* ... */
23
24
mem_3=malloc(...);
25
if(mem_3==NULL){
26
ret_val=-3;
27
}else{
28
/* ... */
29
30
mem_4=malloc(...);
31
if(mem_4==NULL){
32
ret_val=-4;
33
}else{
34
/* ... */
35
36
mem_5=malloc(...);
37
if(mem_5==NULL){
38
ret_val=-5;
39
}else{
40
/* ... */
41
}
42
}
43
}
44
}
45
}
46
47
free(mem_5);
48
free(mem_4);
49
free(mem_3);
50
free(mem_2);
51
free(mem_1);
52
53
returnret_val;
54
}
Oder so:
1
intfoobar(void)
2
{
3
...
4
mem_5=malloc(...);
5
if(mem_5==NULL){
6
ret_val=-5;
7
}else{
8
/* ... */
9
10
free(mem_5);
11
}
12
13
free(mem_4);
14
}
15
16
free(mem_3);
17
}
18
19
free(mem_2);
20
}
21
22
free(mem_1);
23
}
24
25
returnret_val;
26
}
In dieser Variante brauchen die Pointer wieder nicht mit NULL
initialisiert zu werden.
Schoen ist das aber alles nicht. In diesem, gar nicht mal so speziellen
Beispiel (Stichwort: Treiberprogrammierung), ist goto fuer mich allen
anderen Konstruken haushoch ueberlegen, was die Les- und Wartbarkeit,
sowie die Laufzeit angeht.
Yalu X. schrieb:> Die meisten wissen auch nicht, dass der reißerische Titel des Artikels> gar nicht von Dijkstra selbst, sondern von Wirth stammt
Immer hin: Wikipedia weiss das. :)
https://de.wikipedia.org/wiki/Sprunganweisung#Umstrittene_Verwendung_von_GOTO
1
1968 sprach sich Edsger W. Dijkstra in seinem Aufsatz
2
"Go To Statement Considered Harmful" (der Titel geht
3
allerdings auf Niklaus Wirth zurück), für eine Abschaffung
4
des Goto-Befehls in allen höheren Programmiersprachen aus.
5
6
...
7
8
In der Praxis hat sich jedoch gezeigt, dass der Verzicht auf
9
Goto zwar möglich ist, jedoch in einigen Fällen zu sehr aufwändigen
10
Konstrukten führt. So hält Donald E. Knuth Goto für die optimale
Kaj G. schrieb:> mem_1 = malloc(10);> if (mem_1 == NULL) {> return -1;> }>> /* do fancy stuff */
ist aber auch mit Seitenausgang was man meiden sollte, soweit war ich
mit meinem Code auch schon, gefiel mir aber auch nicht.
Joachim B. schrieb:> ist aber auch mit Seitenausgang was man meiden sollte
Das gibt schon wieder Potential für Diskussionen ;-)
Aber mich interessiert was anderes:
Nachdem ich obigem Link zu Wikipedia gefolgt bin, lese ich da folgendes:
> In Sprachen, welche Ausnahmenbehandlung erlauben, wird dagegen die> Ein-Ausstiegspunkt-Regel als obsolet angesehen, da throw-Anweisungen die> Argumentation hinter dieser Regel ad absurdum führen.
Erklärt mir mal jemand glaubhaft, wie man mit Exceptions lesbar ein
break, next, last oder continue schreibt?
Ich dachte ja immer, Exceptions wären Exceptions, wie der name schon
sagt...
Yalu X. schrieb:> Da das hier nun bereits die x-te Diskussion zum Thema> Goto ist (x≥10),
Naja, Diskussionsforen sind halt wie Schulklassen: Jedes
Jahr schlagen wieder Blödmänner auf, die nicht wissen,
wieviel 1+1 ist.
In diesem Fall war (wieder einmal) ich dieser Blödmann.
> Wann habt ihr zum letzten Mal Quellcode in C, Pascal> oder irgendeiner anderen Programmiersprache mit> strukturierenden Sprachelementen gesehen, der Gotos in> einer Art und Weise verwendet, die tatsächlich an die> berühmten italienischen Nudeln erinnert?
Noch nie, soweit ich das übersehe.
> Bei mir ist das geschätzte 30 Jahre her. Damals und in> den Jahren davor wollten viele Leute vom Basic auf ihrem> Heimcomuter (Commodore, Apple, Atari und wie sie alle> hießen) auf modernere Sprachen wie Pascal und C umsteigen,> wussten aber zunächst mit den neu hinzugekommenen Features> wie If-Then-Else, For-/While-Schleifen und> Funktionen/Prozeduren mit Argumentlisten nicht viel> anzufangen. Entsprechend gruselig und Basic- ähnlich sahen> ihre Programme aus.
Hmm. Nach meinem Gefühl war (mangels einschlägiger Computer)
die BASIC-Welle im Osten nicht so hoch. Ich bin in der
zweiten Hälfte der 80er so großgeworden, dass man strukturiert
programmieren soll, wenn man es anständig machen will. Klar
ist das mit'm Assembler etwas schwierig, aber das sollte das
Ziel sein.
> Muss man also die Diskussion um das Für und Wider von> Goto
Nein, das ist ein Missverständnis.
Ich brauche goto nicht und muss dessen Für und Wider daher
auch nicht diskutieren.
Ich wollte wissen, warum die C-Programmierer, die einerseits
zugeben, dass man goto nur relativ selten braucht, andererseits
VEHEMENT dagegen sind, es komplett zu verbieten.
Ich wollte keine technische, sondern eine psychologische Frage
klären.
Ich wollte etwas über C lernen, indem ich etwas über die
Mentalität des C-Programmierers lerne :)
> immer wieder von Neuem beginnen, oder hat sich das Problem> Wirklichkeit schon längst erledigt?>> Ich meine, letzteres ist der Fall.
Jein: Das "ursprüngliche" Problem mit goto, auf das sich
der Dijkstra-Artikel bezieht, ist sicherlich schon lange
behoben.
Aber: Die Fragen nach goto, strukturierter Programmierung
und ähnlichem haben (auch) einen automatentheoretischen
Hintergrund, bei dem ich das diffuse Gefühl habe, er werde
sträflich vernachlässigt (weniger in der täglichen Programmier-
praxis, sondern primär in Lehre und Forschung). Im Beitrag
von Nop sind diese Dinge angeklungen.
Man kann Querverbindungen zur Steuerungsprogrammierung, zu
programmierbarer Logik, zu den aktuellen Sicherheitslücken
und schätzungsweise auch zur funktionalen Programmierung
ziehen.
> Die meisten wissen auch nicht, dass der reißerische Titel> des Artikels gar nicht von Dijkstra selbst, sondern von> Wirth stammt
Naja, das ist aus dem Pdf mit seinem Artikel nicht zu ersehen.
> (der ein paar Jahre später witzigerweise das Goto in sein> Pascal eingebaut hat :)).
Ja! Schande über ihn!
Und "Hoch Ousterhout" dafür, dass er dieser Versuchung
widerstanden hat!
Kaj G. schrieb:> Possetitjel schrieb:>> Das ist aber nur ein LAUFZEITNACHTEIL und hat nichts mit>> der Lesbarkeit zu tun.>> Doch, das hat sehr wohl was mit der Les- und Wartbarkeit> zu tun.
???
Ich verstehe Dein Beispiel nicht.
[...]
> So, ein letztes, hinkendes Beispiel hab ich noch :P
Ich stricke Dein Beispiel mal so um, wie ich es meine.
Ich hoffe, das Prinzip wird erkennbar, obwohl ich kein
C kann; Syntaxfehler sind wahrscheinlich.
Yalu X. schrieb:> Wann habt ihr zum letzten Mal Quellcode in C, Pascal oder irgendeiner> anderen Programmiersprache mit strukturierenden Sprachelementen gesehen,> der Gotos in einer Art und Weise verwendet, die tatsächlich an die> berühmten italienischen Nudeln erinnert?
Wir haben hier ein größeres Projekt, > 100kLoc. Und als dann 61508 (SIL,
Funktionale Sicherheit) anlag, kam mein Chef: "Kollege X fiel auf, Du
verwendest goto. Bring das bitte in Ordnung". Naja, das war ein
modifiziertes printf aus der Stdlib, das halt im Orignal ein paar
(sinnvolle) gotos hat. Nee, sag ich, dann war's OK.
Das Interessante: X's Leute liebten Gotos. Mit Sprung in Else-Zweige
etc. An einem Tag haben sie 3 Dutzend Gotos formal durch
for(;;)/Switch-Case/continue ersetzt. Gut, Umarbeitung wäre
fehlerträchtig, aber hey, gotos durch noch was bescheuertes ersetzen ist
ganz sicher nicht Dijkstras Sinne.
Jedenfalls bin ich jetzt offiziell der einzige Spaghettiprogrammierer
;-)
Yalu X. schrieb:> Wann habt ihr zum letzten Mal Quellcode in C, Pascal oder irgendeiner> anderen Programmiersprache mit strukturierenden Sprachelementen gesehen,> der Gotos in einer Art und Weise verwendet, die tatsächlich an die> berühmten italienischen Nudeln erinnert?
Im FORTRAN-Praktikum an der Uni. :)
In der Tat mehr als 30 Jahre her. Ich war froh, als wir auf dem
PDP11-Clone des Fachbereichs unseren Pascal-Compiler zum Laufen bekommen
hatten. Dann konnte ich FORTRAN endlich zu den Akten legen.
Michael R. schrieb:> Joachim B. schrieb:>> ist aber auch mit Seitenausgang was man meiden sollte>> Das gibt schon wieder Potential für Diskussionen ;-)
Die sind irgendwie mit Goto und #define vergleichbar.
(vermutlich kann man jedes Sprachmittel dort einsetzen)
Jeder vermiedene Seitenausstieg ist ein guter Seitenausstieg.
Jeder vermeidbare Seitenausstieg ist ein böser Seitenausstieg.
Und das wieder mit der bekannten Unschärfe:
Kein Eiertanz wegen eines, der Situation unangemessenen, Dogmas.
z.B. gerade in ISRs machen schnelle Ausstiege gerne Sinn
Possetitjel schrieb:> Man sollte "for" als Ausgeburt eines Sprachsadisten verbieten> und nur "while" und "do-while" erlauben...
Bei Go (golang) gibt es nur noch "for" aber kein "while" und erst recht
kein "do-while". Die Schöpfer der Sprache meinten, dass das
übersichtlicher bzw. weniger verwirrend sei. "goto" haben sie allerdings
nicht wegrationalisiert ;)
Hier ein kleines Beispiel (aus meiner Erinnerung) für ein sinnvollen
Seitenausstieg (oder auch nicht). Hier werden alle bytes von einem
Ringbuffer gelesen. Ist der Ringbuffer leer gibt es ein -1 zurück und
darauf der Ausstieg.
1
voidcommandHandler(void)
2
{
3
uint8_tcommand[80];
4
uint8_tbyte;
5
staticuint8_tindex;
6
do
7
{/*uart_get empty -> -1*/
8
if(uart_get(&byte))return;
9
command[index++]=byte;
10
}while(byte!='\r');
11
commandInterpeter(command);
12
index=0;
13
}
Ich weiß jetzt nicht bei wem sich die Fußnägel aufrollen, aber ich finde
hier das return sinnvoll.
Christopher J. schrieb:> aber kein "while"
Naja, for(;x;) benötigt auch nicht mehr Zeichen als das äquivalente
while(x).
Zudem verstößt (in C) while(1) gegen die meisten Regeln, während for(;;)
nicht nur explizit erlaubt ist, sondern sogar TEUREN Quelltext-Speicher
spart.
p41145 schrieb:> { /*uart_get empty -> -1*/> if (uart_get(&byte)) return;
Lies Dir mal den Kommentar durch. Wann wird nach dem Aufruf von uart_get
die Funktion beendet?
Davon abgesehen ist das hässlich formatiert - das return sollte, damit
es auffällt, definitiv in einer eigenen Zeile und nicht hinten an das
if-Statement drangeklatscht werden.
Des weiteren ist das ein typischer Fall eines nicht abgefangenen Buffer
Overflows; was geschieht, wenn die UART hier mehr als 80 Zeichen
empfängt, aber keines davon ein '\r' ist?
p41145 schrieb:> do> { /*uart_get empty -> -1*/> if (uart_get(&byte)) return;> command[index++] = byte;> } while (byte != '\r');
1
while(uart_get(&byte)==0&&byte!='r')
2
{
3
command[index++]=byte;
4
}
finde ich jetzt auch nicht schlimmer.
Wobei ich nichts vom Verbot des frühen Ausstiegs halte. Standards, die
das immer noch verbieten sind m.E. outdated.
Autsch!
Den wesentlichen Fehler in dieser Funktion hat noch niemand bemängelt:
Buffer Overflow!
Da muss unbedingt eine Überprüfung des index auf Gültigkeit rein.
Rufus Τ. F. schrieb:> Lies Dir mal den Kommentar durch. Wann wird nach dem Aufruf von uart_get> die Funktion beendet?
na, wenn der Uart-Puffer leer ist. So wie es sein sollte, oder?
Rufus Τ. F. schrieb:> Des weiteren ist das ein typischer Fall eines nicht abgefangenen Buffer> Overflows;
Der Code scheint so runter geschrieben zu sein, das return würde eh
alles zerstören.
Rufus Τ. F. schrieb:> Lies Dir mal den Kommentar durch. Wann wird nach dem Aufruf von uart_get> die Funktion beendet?
Meiner Meinung nach direkt nach der if-Abfrage, falls der Buffer leer
ist. Bin da auf dem Holzweg, was daran verkehrt ist?! Bei dem Rest geb
ich natürlich recht, allein command[] müsste static sein. War jetzt auch
nur schnell runtergeschieben als Beispiel.
Achim S. schrieb:> while(uart_get(&byte)==0 && byte !='r')> {> command[index++] = byte;> }> finde ich jetzt auch nicht schlimmer.
danach müsste jedoch der anschließende Code auch mit "byte !='r'"
abgefangen werden. Ja, auch das bläht den Code jetzt nicht unnötig auf,
wobei ein direkter Ausstieg wohl etwas schneller ist.
Thosch schrieb:> Und der Index ist im ersten Aufruf ebenfalls nicht initialisiert...
als static nicht unbedingt nötig
Achim S. schrieb:> Zudem verstößt (in C) while(1) gegen die meisten Regeln, während for(;;)> nicht nur explizit erlaubt ist, sondern sogar TEUREN Quelltext-Speicher> spart.
Gibt es tatsächlich solche Regeln die while(1) verbieten aber for(;;)
erlauben? Irgendwelchen MISRA-Guidelines würde ich das ja glatt zutrauen
;)
Christopher J. schrieb:> Gibt es tatsächlich solche Regeln die while(1) verbieten aber for(;;)> erlauben? Irgendwelchen MISRA-Guidelines würde ich das ja glatt zutrauen> ;)
Dem ist auch so, und das aus gutem Grund. Nicht nur, daß die for-Version
die schon von K&R definierte Version ist, sondern man hat damit auch
nicht das Problem, unabsichtlich eine while-Bedingung zu schreiben, die
irrtümlich immer zu "wahr" auswertet.
Rufus Τ. F. schrieb:> Des weiteren ist das ein typischer Fall eines nicht abgefangenen Buffer> Overflows; was geschieht, wenn die UART hier mehr als 80 Zeichen> empfängt, aber keines davon ein '\r' ist?
das waren meine Gedanken, aber da ich nicht so extrem sattelfest in C
bin ist es gut das du es anmerkst!
Nop schrieb:> Christopher J. schrieb:>>> Gibt es tatsächlich solche Regeln die while(1) verbieten aber for(;;)>> erlauben? Irgendwelchen MISRA-Guidelines würde ich das ja glatt zutrauen>> ;)>> Dem ist auch so, und das aus gutem Grund. Nicht nur, daß die for-Version> die schon von K&R definierte Version ist, sondern man hat damit auch> nicht das Problem, unabsichtlich eine while-Bedingung zu schreiben, die> irrtümlich immer zu "wahr" auswertet.
aber normalerweise nutzt man while( a != b ) weil man was erreichen
will, zum Testen setzt man es mal auf while(1), es bleibt while.
Nun zum Testen while(1) zu for(;;) zu ersetzen ist doch nicht weniger
fehleranfällig, zumal wer der Code lesen und überarbeiten soll.
bei while ist es verständlich das aus Versehen die 1 drin steht,
bei for(;;) grübelt man ne Weile was wollte der Autor hier?
Joachim B. schrieb:> aber normalerweise nutzt man while( a != b ) weil man was erreichen> will
Nö, while-Bedingungen können auch etwas komplexer sein. Da kann sich
dann schnell mal durch einen Tippfehler etwas einschleichen, was zu
"always true" führt, und das sollen statische Analyser anmeckern.
> Nun zum Testen while(1) zu for(;;) zu ersetzen ist doch nicht weniger> fehleranfällig
Zum Testen ist es ja auch egal, was man tut. Der Compiler frißt auch
while(1), und für den Debug-Build kann man die Anmerkungen des Analysers
ignorieren.
> bei for(;;) grübelt man ne Weile was wollte der Autor hier?
Da grübelt man gar nicht, das ist seit K&R-Zeiten einfach C. Wenn man da
einen grübelnden Programmierer hat, ist das ein Fall von PEBKAC.
Nop schrieb:> Da grübelt man gar nicht, das ist seit K&R-Zeiten einfach C.
du verstehst nicht, ich meinte als while Ersetzung
ich finde es halt doof statt der echten Bedingung
while( a != b )
zum Testen
while(1) gegen for(;;) zu ersetzen
aber du hast Recht lieber Gast und das musste mal gesagt werden
for(;;)
Nop schrieb:> das ist seit K&R-Zeiten einfach C
gut das wir drüber geschrieben haben
Nop schrieb:> while-Bedingungen können auch etwas komplexer sein
noch so eine schlaue Bemerkung, hast du noch ein paar?
Joachim B. schrieb:> ich finde es halt doof statt der echten Bedingung while( a != b ) zum> Testen while(1) gegen for(;;) zu ersetzen
Wenn du etwas zum Testen ersetzen willst, wird das keinen Menschen
interessieren.
Es geht doch lediglich darum, dass die Tools für statische Codeanalyse
ein "while (condition)" sauber anmosern können, wenn sie bemerken, dass
"condition" zur Compilezeit konstant "true" ist. Sie gehen dann von
einem Programmiererfehler aus.
Bei "for (;;)" ist dagegen einfach klar, dass der Programmierer das
explizit so hingeschrieben hat. Die Wahrscheinlichkeit, dass sich
dort ein Fehler einschleichen konnte, ist minimal; sie beschränkt sich
auf irgendwelche irrwitzigen Dinge wie:
1
for(A;B;C)
bei denen A, B und C Makros sind, die zu nichts evaluieren. Dass alle
drei Elemente eine for-Anweisungen aus Makros bestehen, ist mir aber
in freier Wildbahn noch nie über den Weg gelaufen.
Joachim B. schrieb:> for(;;)> Nop schrieb:>> das ist seit K&R-Zeiten einfach C>> gut das wir drüber geschrieben haben
Der Standard schreibt explizit, dass
1
for(a;b;c){code;}
und
1
a;while(b){code;c;}
äquivalent sind, dass a, und c entfallen können und das b als non-Zero
gewertet wird, wenn es enfällt.
Der Knackpunkt ist nun, dass b nur bei for entfallen darf.
Man muss ja nicht alles kennen. Ich fände es nur schade, wenn jemand,
der den offiziellen Weg nun kennt, am alten Heck festhalten würde.
Arduino F. schrieb:> while(!stromAusfall)
Da fällt mir was lustiges dazu ein, aus der BeOS API:
1
doubleis_computer_on_fire(void)
>Returns the temperature of the motherboard if the computer is currently on>fire. If the computer isn't on fire, the function returns some other value.
Jörg W. schrieb:> Es geht doch lediglich darum, dass die Tools für statische Codeanalyse> ein "while (condition)" sauber anmosern können, wenn sie bemerken, dass> "condition" zur Compilezeit konstant "true" ist. Sie gehen dann von> einem Programmiererfehler aus.>> Bei "for (;;)" ist dagegen einfach klar, [...]
Das ist doch ein Pseudoargument.
- Erstens koennte der Kompiler alle whiles die konstant true sind, a u
s s e r while(1), anmosern.
- Zweitens kann es vom Programmierer gewollt sein, z.B.:
#define Debugging = 1;
while(InInitialisation or Debugging){}
Druckertreiber schrieb:> Das ist doch ein Pseudoargument.> - Erstens koennte der Kompiler alle whiles die konstant true sind, a u> s s e r while(1), anmosern.
Ja natürlich "könnte". Aber es gibt genau einen dafür im Standard
vorgesehenen Mechanismus. Da ist es sinnlos, darüber zu diskutieren,
dass man es auch anders machen könnte.
Genauso könnte man bei while auch die leere Klammer erlauben (wie bei
for das leere mittlere Element). Hat man aber nicht, und darum ist
while(1) genauso unsinnig wie for(;1;)