mit einem Aufruf aus meinem Programm heraus.
void hat aber die Eigenschaft, dort weiter zu machen, von wo es
aufgerufen wurde, es kehrt also zurück.
Wenn ich goto nutze, ergibt es teilweise eine totale
Unübersichtlichkeit. Ist schlecht nachzuvollziehen wo es weiter geht.
Im Netz wird da von gesprochen, das es verpöönt ist nichrr genutzt
werden soll.
Was nutz ihr bei solchen Sachen?
Paul
Paul schrieb:> Was nutz ihr bei solchen Sachen?
keine Ahnung, dafür musst du uns erst mal zeigen wozu du goto brauchst.
In deinem Beispiel ist das nicht klar.
Paul schrieb:> void hat aber die Eigenschaft
Das hat nichts mit void zu tun. void ist der Rueckgabe wert. Du
koenntest genauso gut int statt void hinschreiben, das verhalten waere
dasselbe.
Besorg dir erstmal ein C-Buch.
Goto ist ein unnötiges Konstrukt. Wenn das Programm nach Ende einer
Funktion nicht "normal" fortgesetzt werden soll, lifert man mit return
einen entsprechenden Statuscode zurück und wertet den aus.
1
// returns 1 on success
2
uint8_t tuwas()
3
{
4
...
5
if (whatever problem)
6
{
7
return 0;
8
}
9
...
10
return 1;
11
}
12
13
void caller()
14
{
15
uint8_t success=tuwas();
16
if (success)
17
{
18
tuNochwas();
19
}
20
else
21
{
22
reagiereAufFehler();
23
}
24
}
Für schleifen gibt es noch break und continue, um den normalen Ablauf zu
unterbrechen.
Häh?
Was?
Da steht nichts, was man ansatzweise verstehen könnte.
Wo nutzt du dort ein goto?
Und ja, ich behaupte auch, wer goto in einer höheren Programmiersprache
nutzt, hat es nicht verstanden.
Oben steht eine Methode/Funktion, die kann aufgerufen werden und gibt
halt keine Wert zurück.
Gib ein besseres Beispiel und man kann dir andere Lösungsmöglichkeiten
bieten.
Ach ja, werft den Purschen zu Poden... verpöönt=>verpönt
> Ist schlecht nachzuvollziehen wo es weiter geht.
Dabei hilft Dir die Entwicklungsumgebung. In Eclipse klickst du mit der
rechten Maustaste auf den namen der Funktion, dann aus
References/Project. Und schon werden alle Stellen aufgelistet, wo diese
Funktion verwendet wird.
Jörg M. schrieb:> Und ja, ich behaupte auch, wer goto in einer höheren Programmiersprache> nutzt, hat es nicht verstanden.
oder er nutzt die alle Möglichkeiten die eine Sprache bietet, statt sich
komplizierten code zu schreiben nur um ein goto zu vermeiden.
Stefan U. schrieb:>> Ist schlecht nachzuvollziehen wo es weiter geht.>> Dabei hilft Dir die Entwicklungsumgebung. In Eclipse klickst du mit der> rechten Maustaste auf den namen der Funktion, dann aus> References/Project. Und schon werden alle Stellen aufgelistet, wo diese> Funktion verwendet wird.
Werden auch die Sprungziele bei goto gezeigt?
(darum geht es hier)
µIP nutzt viele Goto Befehle, das hat mich echt geschockt. Ich dachte
bis dahin immer, das es in C gar kein Goto gäbe.
Aber immerhin ist der Code von µIP noch nicht so schlimm, das ich ihn
als Spaghetti-Code bezeichnen würde. Da geht es noch einigermaßen, weil
es ein simpler Batch-Ablauf ist, den man von oben nach unten lesen kann.
Danke für den Hinweis mit dem C-Buch.
Es gibt Leute die verstehen die Frage sofort und der Hinweis hat sofort
geholfen. Sorry hatte das vergessen oder zu wenig genutzt.
Angere pöbeln lieber rum und geben irgend welche Sinnlose oder Hirnlose
Komentare ab.
Danke Stefan
Paul
Schaut euch mal den Linux-Code an. Da gibt es sehr viele Goto's ;)
Wenn man weiß, wie man damit seinen Code übersichtlicher machen kann,
dann spricht doch nichts gegen die Verwendung, oder?
> Werden auch die Sprungziele bei goto gezeigt? (darum geht es hier)
Achso, Frage missverstanden.
Keine Ahnung, ich habe Goto noch nie benutzt.
Ich wollte es gerade ausprobieren, aber ich kriege das C++ Plugin nicht
heruntergeladen. Habe momentan nur Java installiert.
Hallo,
man kann goto schon verwenden, aber man sollte es nicht übertreiben und
man sollte aufpassen.Im Zweifelsfall, Finger weg.
Zu goto:
- Sinnvoll an Stellen an denen es die Komplexität extrem erhöhen würde.
- Sprünge mit goto sollten immer vorwärts im Controlflow sein.
- Das Sprung-label sollte in der selben Funktion sein.
Falls Du Einsteiger bist:
- "Head First C", weniger Abstrakt als MISRA und ein bisschen mehr Spaß.
Besorge Dir MISRA-C 2012 und das K&R C Buch:
- "The C Programming Language", sollte man haben.
- "MISRA-C 2012"ist der Standard wenn es um C geht, alles andere sind
meist Abwandlungen davon und meist in der gesamtheit nicht wirklich
besser. Die 2012er Version hat gegenüber der 2004er einige
Verbesserungen, vor allem bei der Verständlichkeit
Grüße
Sebastian
Ich habe goto schon hin und wieder benutzt. Z.B. um in einer größeren
Funktion vorzeitig Fehler aufzuräumen.
z.B aus den Fingern gesogen ein Beispiel um etwas vorzeitig abzubrechen.
int complex_io_operation(wchar_t *file, struct *data_block)
{
if( (Open(file) != 0)) {
goto ERROR_1; /* not found? */
}
if( AppendData(data_block) != data_block->size ) {
goto ERROR_2; /* insufficient data written */
}
(...)
return 0;
ERROR_1:
/* individual cleanup code 1 */
return -1;
ERROR_2:
/* individual cleanup code 2 */
return -2;
}
Möglicherweise ein schlechtes Beispiel. Womöglich nicht
Lehrbuch-konform. Man könnte das natürlich anders schreiben, umbiegen
etc., aber ich finde so ist es gut lesbar.
Dogmatische Regeln, die im Extremfall auch nur zitiert werden und
vorgegeben wurden, bremsen einen im Zweifel nur aus.
Man muss alles immer wieder auf den Prüfstand stellen finde ich.
Nun, angesichts dessen dass Du uns sehr wenig Code zum Arbeiten gibst,
kannst Du uns so ein Goto-Konstrukt mal posten? Ich wette um eine
Eiswaffel dass sich dies mit einem der von dirkb2 vorgeschlagenen
Konstrukte lückenlos und weit übersichtlicher ersetzen läßt.
Paul schrieb:> in meinen Programmen nehme ich sehr häufigvoid aufruf()> {> ... tu was> }> mit einem Aufruf aus meinem Programm heraus.> void hat aber die Eigenschaft, dort weiter zu machen, von wo es> aufgerufen wurde, es kehrt also zurück.> Wenn ich goto nutze, ergibt es teilweise eine totale> Unübersichtlichkeit. Ist schlecht nachzuvollziehen wo es weiter geht.> Im Netz wird da von gesprochen, das es verpöönt ist nichrr genutzt> werden soll.> Was nutz ihr bei solchen Sachen?
Ein C-Buch um erst mal die Grundlagen zu erlernen.
Was du geschrieben hast, ist eine Prozedur (das ist die Bedeutung von
void, mit allem anderen wäre es eine Funktion), und die macht ebenso wie
eine Funktion nach einem Aufruf IMMER dort weiter, von wo sie aufgerufen
wurde. Das ist Absicht. Das haben die mit Mühe (einem Stack der
Rücksprungadressen) so gemacht.
Man springt auch nicht aus Prozeduren und Funktionen mit GOTO raus um
irgendwo anders hinzukommen, denn dann könnte man sie nicht mehrmals an
unterschiedlichen Stellen verwenden. Das ist der einzige wirkliche
Grund, etwas in eine Prozedur zu verpacken: Damit man dasselbe an 2
unterschiedlichen Stellen benutzen kann.
Wenn du dein ...tu was verpackt in aufruf sowieso nur ein Mal im
Programm per aufruf() aufrufst, brauchst du es gar nicht erst in eine
Prozedur zu verpacken, schreibe statt aufruf() gleich ....tu was dort
hin.
In fortgeschrittenem C lernt man vielleicht setjmp/longjmp, aber das nur
zur Fehlerbehandlung, in C++ sind das Exceptions.
Aber du steckst offenbar noch in grundlegendem Programmieren und
verpennter deutscher Rechtschreibung fest.
Dirk B. schrieb:> for, while, do-while, if-else, return, break
switch-case hast Du vergessen - das kommt der "klassischen"
goto-Funktion wohl noch am nächsten.
Peter II schrieb:> Jörg M. schrieb:>> Und ja, ich behaupte auch, wer goto in einer höheren Programmiersprache>> nutzt, hat es nicht verstanden.>> oder er nutzt die alle Möglichkeiten die eine Sprache bietet, statt sich> komplizierten code zu schreiben nur um ein goto zu vermeiden.
Nur weil eine Programmiersprache alte Relikte weiter beinhaltet, heißt
es nicht, dass man diese auch nutzen sollte. Wenn man ein goto benötigt,
um "komplizierten" Code zu vermeiden, hat man schon vorher den
Grundstein für zu komplizierten Code gelegt.
> Werden auch die Sprungziele bei goto gezeigt? (darum geht es hier)
Ich hab's jetzt testen können.
Drücke die Strg Taste und klicke dann auf dem Namen des Sprungziels
hinter Goto. Der Cursor springt das zum Ziel und Eclipse markiert es.
Jörg M. schrieb:> Und ja, ich behaupte auch, wer goto in einer höheren Programmiersprache> nutzt, hat es nicht verstanden.
hmmm ich habe einen Fall wo ich trotz C goto verwende, vielleicht gehts
auch anders, ich weiss es nicht.
Ich muss das Beispiel noch mal suchen, aber ich gebe zu goto in C
braucht man eigentlich nicht, aber weil es das doch gibt und ich auch
schon einmal darauf zurückgreifen musste mangels anderer Ideen kann es
nicht so sinnlos sein.
Den jmp gibts ja in Asm auch, also warum goto verteufeln?
Jörg M. schrieb:>> oder er nutzt die alle Möglichkeiten die eine Sprache bietet, statt sich>> komplizierten code zu schreiben nur um ein goto zu vermeiden.>> Nur weil eine Programmiersprache alte Relikte weiter beinhaltet, heißt> es nicht, dass man diese auch nutzen sollte. Wenn man ein goto benötigt,> um "komplizierten" Code zu vermeiden, hat man schon vorher den> Grundstein für zu komplizierten Code gelegt.
goto bei C (nicht C++) zur Fehlerbehandlung ist üblich und sinnvoll.
http://eli.thegreenplace.net/2009/04/27/using-
goto-for-error-handling-in-c
https://silviocesare.wordpress.com/2007/10/24/a-good-use-of-goto-for-error-handling/
Joachim B. schrieb:> Den jmp gibts ja in Asm auch, also warum goto verteufeln?
Und jedesmal wenn er nicht im Sinne eines while/for-repeaters verwendet
wird oder zum Überspringen eines if-Astes gibt's Ärger.
Peter II schrieb:> goto bei C (nicht C++) zur Fehlerbehandlung ist üblich und sinnvoll.
Definitiv, hab ich auch gestern erst so für eine I2C Routine so genutzt.
Da wurde zu erst ein Konfigurationsbyte ausgelesen, ein paar Bits
ausmaskiert und neue Bits gesetzt und das Byte wieder zurück
geschrieben. Der Rückgabewert der Funktion zeigt den Erfolg oder
Misserfolg an.
Hier gab es auch viele Stellen, wo Fehler auftreten können. Wenn zum
Beispiel ein Buszugriff fehlschlägt, muss man vor dem Return noch den
i2c_stop() aufrufen, um den Bus wieder freizugeben. Das Ergebnis war im
ersten Schritt ein furchtbarer Spaghetti Code. Im zweiten Schritt konnte
dank goto sehr stark aufgeräumt werden. Man springt einfach in den
Aufräumbereich am Ende der Funktion, nach dem return 1.
Das ganze lässt wirklich gut erweitern, wie Peter hier verlinkt hat:
https://silviocesare.wordpress.com/2007/10/24/a-good-use-of-goto-for-error-handling/MaWin schrieb:> In fortgeschrittenem C lernt man vielleicht setjmp/longjmp, aber das nur> zur Fehlerbehandlung, in C++ sind das Exceptions.
Das ganze war ein sehr interessanter Einwurf, der bisher hier nicht
weiter aufgegriffen wurde. Ich habe diese beiden Funktionen auch schon
mal gesehen, aber nie wirklich wahrgenommen, nie hinterfragt, geschweige
denn benutzt. Ich denke das wird wohl den meisten so gehen, aber das
Interesse war geweckt und ich habe aber nun mal etwas gegoogled und bin
hierüber gestolptert:
http://www.di.unipi.it/~nids/docs/longjump_try_trow_catch.html
Hier wurde ein komplettes Try-Catch-Finally-Kontrukt über etwas
Preprocesssor-Magic gebaut. Das ganze macht echt einen guten und
durchdachten Eindruck. Hat schon jemand Erfahrung mit solch einer
Konstruktion?
Der Grund warum das funktioniert ist einfach: malloc gibt einen
Nullpointer zurück wenn es failt.
Also wer einen guten Grund für goto sucht muss weitersuchen, hier gibt's
leider keinen.
Joachim B. schrieb:> hmmm ich habe einen Fall wo ich trotz C goto verwende
Es gibt halt Sachen im Leben, die man besser niemandem sagen oder zeigen
sollte.
> Den jmp gibts ja in Asm auch, also warum goto verteufeln?
Es ist ein Wortsuchspiel, man muss den Label erst mal finden im
Quelltext. Das ist unübersichtlich. (Auch) daher ist ASM
unübersichtlich. Schade, daß du das nicht selber bemerkst.
Dann auch noch aus einer Prozedur zu springen wie Paul es vor hat, ist
ganz schlechter Programmierstil. Das macht man höchstens, wenn man ein
Programm nach Fehler hart abbrechen will (exit). Das passiert bei einem
uC nie, was soll auch nach dem das Programm endet passieren ?
Setjmp auf einem uc finde ich gerade in Verbindung mit Interrupts recht
gefährlich. Da legt man sich schnell ein Ei mit falschem Kontext oder
falschen Flags.
MaWin schrieb:> Es gibt halt Sachen im Leben, die man besser niemandem sagen oder zeigen> sollte.
stimmt du hast so recht
Beitrag "Re: Relais Ersatz in kleinster Bauform"MaWin schrieb:> Dann auch noch aus einer Prozedur zu springen
da hast du auch recht, das mache ich nicht und da sollte man goto auch
nicht verwenden.
Matze schrieb:> Wenn man weiß, wie man damit seinen Code übersichtlicher machen kann,> dann spricht doch nichts gegen die Verwendung, oder?
Was im Endeffekt heißt: Als Anfänger lässt man gefälligst die Finger
davon. ;-)
Es gibt schon einen Grund warum goto verpönt ist, bei übermäßigen
Einsatz macht es ein Programm unwartbar.
Gerade wenn jemand programmieren lernt, sollte er darauf verzichten.
Wenn man weiß was man tut, dann kann ein goto durchaus Sinn machen.
zB der klassische Ressourcenstackabbau im Fehlerfall. Das verringert
dann die Einrückungsebenen.
Mir fällt ein spezieller Fall ein, wo goto bei Error Handling
tatsächlich Sinn macht:
Man könnte zwar den Aufräum-Code in eine separate Funktion packen, wie
im Code von Heinz L.. Dies hat aber zusätzliche Funktionsaufrufe zur
Folge, was Ausführungszeit und Kompilatgröße betrifft. Zumindest, wenn
der Aufräumcode von mehreren Stellen aus aufgerufen wird.
Ich habe mal einen Fall mitbekommen, wo es auf jedes eingesparte
Flash-Byte ankam. Wegen sehr großer verbauter Stückzahl war es nicht
möglich, einfach den nächstgrößeren µC zu verwenden.
Eine Renaissance des Goto? OMG!
Rein syntaktisch ist Goto in C vollkommen überflüssig. Praktisch ist es
nur in EXTREM wenigen Situationen gerechtfertigt.
Falk B. schrieb:> Praktisch ist es> nur in EXTREM wenigen Situationen gerechtfertigt.
sag ich doch, selten wenn man weiss warum oder man keine andere Lösung
sieht, das heisst ja nicht das es nicht auch ohne goto ginge, aber
manchmal geht Ergebnis vor Schönheit.
> zB der klassische Ressourcenstackabbau im Fehlerfall.
Den Ressourcenstackabbau implementiere ich (in allen Sprachen) anders.
Beispiel in Pseudo-Code:
1
File input=0;
2
File output=0;
3
Converter converter=0;
4
try
5
{
6
input=new File("filename1");
7
output=new File("filename2");
8
converter=new Converter(params);
9
while (input.hasMore())
10
{
11
line=input.readLine();
12
output.writeLine(converter.convert(line));
13
}
14
}
15
finally
16
{
17
if (converter!=0) converter.close();
18
if (output!=0) output.close();
19
if (input!=0) input.close();
20
}
Anmerkung: In diesem beispiel gehe ich davon aus, dass die close
Methoden niemals Exceptions werfen. Ansonsten müsste ich sie einzeln
abfangen.
Stefan U. schrieb:> Beispiel in Pseudo-Code:
Das fällt aber unter die schlechten Beispiele aus dem Gruselkabinett des
codens.
Da gehören 3 try/catch Blöcke hin (ein 4. für das while).
MaWin schrieb:> Da gehören 3 try/catch Blöcke hin (ein 4. für das while).
WAAAAS? (am Inroniedetektor rüttel, hoffentlich ist er kaputt)
Das einzige, was man hier bemängeln kann, ist dass keine
Fehlerbehandlung erfolgt. Es gibt kein catch.
Wenn du meinst, dass man um jeden einzelnen Befehl ein try/catch machen
soll tut mir der leid, der deinen Code lesen muss.
Heinz L. schrieb:> Also wer einen guten Grund für goto sucht muss weitersuchen, hier gibt's> leider keinen.
Ja, du hast auch die Aufgabenstellung leicht modifiziert und ein Array
von Pointern genommen. Mieser Trick. Trotz des Tricks sieht deine Lösung
ziemlich hässlich aus.
Da sind wir dann beim eigentlichen Punkt:
Ab wann ist Prinzipienreiterei wichtiger als klarer Code?
In der While-Programmiersprache gibt es kein goto, und die ist
turingmächtig. Da es in C die While-Schleife gibt ist C auch (ohne goto)
turingmächtig. Goto gibt es nur noch um kompatibel zu altem Code zu
bleiben. Es gibt aber keinen Grund mehr es zu benutzen.
Jay schrieb:> Heinz L. schrieb:>> Also wer einen guten Grund für goto sucht muss weitersuchen, hier gibt's>> leider keinen.>> Ja, du hast auch die Aufgabenstellung leicht modifiziert und ein Array> von Pointern genommen. Mieser Trick. Trotz des Tricks sieht deine Lösung> ziemlich hässlich aus.>> Da sind wir dann beim eigentlichen Punkt:>> Ab wann ist Prinzipienreiterei wichtiger als klarer Code?
Du hast 4 Variablen vom gleichen Typ die offensichtlich mehrere
Gemeinsamkeiten haben, gleichzeitig initialisiert und zerstört werden
sollen. Hier KEIN Array zu verwenden wäre selten dämlich.
Ehrlich gesagt find ich meine Lösung um Längen übersichtlicher als die
Goto-Wurst vom Original. Soll ich's in ein Objekt verpacken damit der
ganze "unschöne" Code wegabstrahiert wird?
informatik student schrieb:> In der While-Programmiersprache gibt es kein goto, und die ist> turingmächtig. Da es in C die While-Schleife gibt ist C auch (ohne goto)> turingmächtig. Goto gibt es nur noch um kompatibel zu altem Code zu> bleiben.
was hat das eine mit dem anderen zu tun? Niemand bezweifelt das man ohne
goto programmieren kann - aber dann teilweise umständlicher
> Es gibt aber keinen Grund mehr es zu benutzen.
doch, um code einfach und übersichtlich zu machen.
> und in Sprachen ohne Exception/Finaly?
Um Exception Handling gings mir in meinem Beispiel gar nicht. Man kann
auch in C vorzeitig aussteigen, um in den Aufräumblock zu kommen. Zum
Beispiel in c
1
int result=ERROR;
2
void* input=0;
3
void* output=0;
4
void* converter=0;
5
do
6
{
7
input=whatever;
8
if (fehler) break;
9
output=whatever;
10
if (fehler) break;
11
converter=whatever;
12
if (fehler) break;
13
...
14
tuwas
15
if (fehler) break;
16
...
17
result=SUCCESS;
18
}
19
while(0);
20
if (converter) { close converter};
21
if (output) { close output};
22
if (input) { close input};
23
return result;
> Da gehören 3 try/catch Blöcke hin (ein 4. für das while).
Wenn die close() Aufrufe Exceptions werfen können, hast du Recht. In
diesem Fall wollten wir allerdings nicht über das Eception Handling
diskutieren, sondern über das Aufräumen von Ressourcen, die zum teil gar
nicht belegt wurden.
> Das einzige, was man hier bemängeln kann, ist dass keine> Fehlerbehandlung erfolgt. Es gibt kein catch.
Richtig. War Absichtlich ausgelassen.
informatik student schrieb:> Da es in C die While-Schleife gibt ist C auch (ohne goto)> turingmächtig. Goto gibt es nur noch um kompatibel zu altem Code zu> bleiben. Es gibt aber keinen Grund mehr es zu benutzen.
Du hast die Mächtigkeit einer Sprache / Maschine nicht verstanden.
Lese das Skipt nochmal und stelle heraus, was man mit der Mächtigkeit
beschreibt und welche Aspekte eben nicht.
Stichworte:
- Menge der Lösbaren Probleme
- Struktur
- Beweisbarkeit / Verifikation
- Effizienz
PS: http://www.wolframscience.com/prizes/tm23/TM23Proof.pdf ist deiner
Argumentation nach das Ultima Ratio, kann alles, warum also noch den
alten komplizierten Kram benutzen?
Stefan U. schrieb:> Um Exception Handling gings mir in meinem Beispiel gar nicht. Man kann> auch in C vorzeitig aussteigen, um in den Aufräumblock zu kommen. Zum> Beispiel in c
Ein gutes Beispiel, wie man es nicht machen sollte. Du umgehst goto
nicht, um schlechten Code zu vermeiden, du umgehst aus Prinzip und
ersetzt es durch einen Missbrauch von while und erzeugst damit erst
schlechten Code.
MaWin schrieb:> und weil wir in C++ Exceptions haben [...]
Ich bin mir nicht sicher ob das ein Beispiel sein soll oder eher zeigt
wie man es genau nicht machen soll. Ich hoffe jedenfalls das so niemand
C++ programmiert.
Also goto kann sinnvoll sein nur muß man auch wissen was man damit
anrichten kann.
Wer wild im Programm herumspringt kann sich schnell raceconditions oder
schlimmeres einfangen.
Von malloc/free mal ganz abgesehen.
Assembler kann man mit passenden Sprungnamen sehr übersichtlich
gestalten, gilt natürlich erst recht für Prozedurale oder OO Sprachen.
Das schöne an höheren Sprachen ist aber das sich der Compiler um das
sichern und rücksichern der Register usw. kümmert, während man das in
Assembler idR zu Fuß machen muß.
Wenn Du bei einem bestimmten Event etwas anderes als die nächste
Funktion aufrufen willst, dann bietet sich das erwähnte switch/case an
und das ganze als Statemachine um die Übergänge auch korrekt zu haben.
Wenn man ja wüßte wo das eigentliche Problem liegt (außer das keine C
Kenntnisse vorliegen) ?
$ cd linux-src
$ grep -R "goto \\w\\+;" * | wc -l
124065
So schlimm kann die Verwendung von goto in C nicht sein wenn es im
durchaus als qulitativ wertig anzusehenden Linux Kernel über 100k mal
zum Einsatz kommt.
Matthias
Μαtthias W. schrieb:> So schlimm kann die Verwendung von goto in C nicht sein wenn es im> durchaus als qulitativ wertig anzusehenden Linux Kernel über 100k mal> zum Einsatz kommt.
Hehehe...
;-)
...und da sitzen sie mit offenem Mund vor dem Monitor und staunen, die
SPEZIALISTEN.
Μαtthias W. schrieb:> So schlimm kann die Verwendung von goto in C nicht sein wenn es im> durchaus als qulitativ wertig anzusehenden Linux Kernel über 100k mal> zum Einsatz kommt.
Wobei ich annehme, dass der ziemlich hardwarenah programmiert ist und
deshalb Konstrukte verwendet wurden, die man im Alltag nicht unbedingt
verwenden sollte (wenn man im Alltag nicht gerade Kernelprogrammierer
ist ;-) ).
Goto hat ja seine Berechtigung, nur eben absolut nicht für Anfänger, die
damit Kontrollstrukturen umgehen wollen, 'weil es ja nicht anders geht'.
Μαtthias W. schrieb:> So schlimm kann die Verwendung von goto in C nicht sein wenn es im> durchaus als qulitativ wertig anzusehenden Linux Kernel über 100k mal> zum Einsatz kommt.
Und wer programmiert Betriebssysteme? Genau - nur wenige Menschen. Und
die wissen eben was sie tun.
Dussel schrieb:> Wobei ich annehme, dass der ziemlich hardwarenah programmiert ist und> deshalb Konstrukte verwendet wurden, die man im Alltag nicht unbedingt> verwenden sollte (wenn man im Alltag nicht gerade Kernelprogrammierer> ist ;-) ).
nein, nur ein kleiner Teil ist Hardware nah.
goto wird oft zum aufräumen verwendet. "goto error;"
Mark B. schrieb:>> Goto hat ja seine Berechtigung, nur eben absolut nicht für Anfänger>> Vollkommen richtig.
achso, Anfänger sollen also umständlichen Code schreiben und keine
Resourcen aufräumen?
Die Beispiele von oben mit dem aufräumen von Resoucen kommen sehr oft
auch bei Anfängern vor. Da ist goto das richtige mittel.
Das sollte Anfänger beachtet, wenn sie goto einsetzen:
Sebastian schrieb:> - Sinnvoll an Stellen an denen es die Komplexität extrem erhöhen würde.> - Sprünge mit goto sollten immer vorwärts im Controlflow sein.> - Das Sprung-label sollte in der selben Funktion sein.
Mark B. schrieb:> Μαtthias W. schrieb:>> So schlimm kann die Verwendung von goto in C nicht sein wenn es im>> durchaus als qulitativ wertig anzusehenden Linux Kernel über 100k mal>> zum Einsatz kommt.>> Und wer programmiert Betriebssysteme? Genau - nur wenige Menschen. Und> die wissen eben was sie tun.
Ohne das jetzt zum Win10-Hassthread umzuwidmen, aber war da nicht erst
kürzlich was wo so 'n Systemupdate das System in den Orkus geschossen
hat?
Oder die Möglichkeit bei einer Maschine auf der Linux läuft mittels
Löschung der falschen Files in /proc nicht nur das OS sondern das BIOS
so zu schrotten dass dabei ein teurer Briefbeschwerer rauskommt?
Also... auch OS-Progger bauen Mist, sind ja auch nur Menschen.
Um es mit dem Meistern zu sagen (Kernighan+Ritchie):
[Kapitel 3.8]
C verfügt auch über eine beliebig zu missbrauchende goto-Anweisung und
Marken, zu denen gesprungen werden kann. Formal ist goto niemals
notwendig, und man kann fast immer leicht ohne goto-Anweisung auskommen.
....
Mit einigen wenigen Ausnahmen, wie den hier zitierten, ist Code mit
goto-Anweisungen im allgemeinen schwieriger zu verstehen und zu pflegen,
als Code ohne goto. Wir wollen zwar nicht dogmatisch werden, aber es
scheint doch, dass goto-Anweisungen wenn überhaupt, dann selten benutzt
werden sollen.
[Kapitel Ende]
Peter II schrieb:> achso, Anfänger sollen also umständlichen Code schreiben und keine> Resourcen aufräumen?>> Die Beispiele von oben mit dem aufräumen von Resoucen kommen sehr oft> auch bei Anfängern vor.
Doch wohl eher nicht auf Mikrocontrollern, wenn man gerade mit Mühe und
Not seine erste LED blinken lässt. Vielleicht wenn man als Anfänger auf
dem PC eine lineare Liste ausprogrammiert oder sowas in der Art.
Ich bezweifle dass die meisten Anfänger mit malloc() und fopen() wild um
sich schmeißen. Jedenfalls wenn es um µC Programmierung geht.
@danvet (Gast)
>Um es mit dem Meistern zu sagen (Kernighan+Ritchie):>[Kapitel 3.8]>C verfügt auch über eine beliebig zu missbrauchende goto-Anweisung und>Marken, zu denen gesprungen werden kann. Formal ist goto niemals>notwendig, und man kann fast immer leicht ohne goto-Anweisung auskommen.
Was nun - "niemals", oder (negiert) "fast immer"?
Jens G. schrieb:> Formal ist goto niemals>>notwendig, und man kann fast immer leicht ohne goto-Anweisung auskommen.>> Was nun - "niemals", oder (negiert) "fast immer"?
du hast das "leicht" überlesen:
man kann immer ohne goto auskommen
und
man kann fast immer leicht ohne goto auskommen
gut, ich gebe mich geschlagen ;-)
Aber wenn man lt. Prinzip schwer ohne goto auskommen muß, dann wird's
wohl vielleicht doch etwas umständlich - oder?
Kommt jedenfalls doch etwas auf den Anwendungsfall an ...
Stefan U. schrieb:> Goto ist ein unnötiges Konstrukt.informatik student schrieb:> Goto gibt es nur noch um kompatibel zu altem Code zu> bleiben. Es gibt aber keinen Grund mehr es zu benutzen.Joachim B. schrieb:> hmmm ich habe einen Fall wo ich trotz C goto verwende, vielleicht gehts> auch anders, ich weiss es nicht.
ist nicht von mir, ist von U.Radig
wie gehts elegant ohne goto?
Falk B. schrieb:> Als erstes mal mit weniger Leerzeilen!
wo denn? :)
als ich es merkte korrigiert
passiert immer wenn die Sourcefiles über den Webserver kommen und hier
per C & P reinkamen, mir ist unklar wo aus 0d 0a die ganzen zusätzlichen
0a herkommen, ich schmeisse die oft mit hexedit raus, immer sehe ich die
nicht im Editor
cool, nur so unwissend ist U.Radig ja nicht, hat er es nicht gesehen
oder gibts andere Gründe?
Egal es gibt viele Wege nach Rom und später ist man immer schlauer,
meist jedenfalls.
Ich würde mein Hirn nehmen.
Schreibe ich einfach so vor mich hin - Spagetti Code - darf ich mich
nicht wundern, wenn es plötzlich heißt: "Schnell weg hier!"
Praktisch immer handelt es sich um einen - lach nicht - vorhersehbaren
Fall.
Es gibt aber so viele Kontrollfunktionen, um im Falle eines Falles etwas
anderes zu machen.
Mit if lässt sich beliebig viel Code ein- bzw. ausblenden.
In Schleifen helfen continue oder break.
In Funktionen hilft auch eventuell ein Einfaches if …. return.
Mittels switch () kann man die Fälle einfach selektieren und alles, was
nicht passt der else überlassen.
Joachim B. schrieb:> cool, nur so unwissend ist U.Radig ja nicht, hat er es nicht gesehen> oder gibts andere Gründe?
Er will keine Unterprogramme verwenden?
nichtCler schrieb:> Er will keine Unterprogramme verwenden?
???
war weder vorher ein Unterprogramm und ist auch keines mit Falk seiner
Lösung, läuft jetzt augenscheinlich gleichwertig und ich gestehe, das
goto hier war entbehrlich.
Sagt mal Männer,
goto manipuliert doch eigentlich direkt den Programm/Instruktion
Counter.
Wenn ich also tief in irgendwelchen Unterfunktionen hänge und nun wild
mit goto rumspringe, dann läuft mir doch irgendwann der heap oder Stack
über, weil vor dem Aufruf einer Unterfunktion stets relevante Register
sowie PC gesichert werden?
Erbitte Erleuchtung.
Joachim B. schrieb:> nichtCler schrieb:>> Er will keine Unterprogramme verwenden?>> ???>>> war weder vorher ein Unterprogramm und ist auch keines mit Falk seiner> Lösung, läuft jetzt augenscheinlich gleichwertig
Warum er Falk seine Lösung nicht genommen hat, weiß ich nicht. Er hätte
meiner Meinung nach "ConversionLoop" als Unterprogramm deklarieren
können und überall wo es gebraucht wird aufrufen können, gefolgt von
einem break im switch-case. Weil er das nicht gemacht hat, dachte ich,
daß er keine Unterprogramme verwenden möchte. Bin in C nicht so firm.
Gibt möglicherweise andere Hinderungsgründe mit knappem Speicher, Stack
oder sonstwas.
>Erbitte Erleuchtung.
Da ich goto nicht verwende kann ich Dir keine echte Erleuchtung bringen.
Ich glaube aber, irgendwo mal aufgeschnappt zu haben, dass der Compiler
weiß wo Du bist und demzufolge den Stapel poliert. Das hat natürlich
seine Grenzen, wenn Du in der Mitte einer Funktion tschüss sagst um
mitten in einer anderen Sequenz weiterzumachen. Das "Polieren", an der
Stelle ist wohl nicht das Problem, aber einen passenden Stapel, am Ziel,
"unterzulegen" wird es wohl sein.
Dummbernd schrieb:> Erbitte Erleuchtung.
Aus falschen Annahmen folgt Willkürliches. Was "goto" genau tut, ist in
der Semantik der Programmiersprache festgeschrieben und im Normallfall
nicht "ich setze PC einfach auf einen neuen Wert".
In C kann goto nicht in die Mitte einer anderen Funktion springen, wenn
ich recht informiert bin. Dafür gibt es setjmp/longjmp, die räumen den
Stack auf. Für den Heap bist du selbst verantwortlich.
Joachim B. schrieb:> cool, nur so unwissend ist U.Radig ja nicht, hat er es nicht gesehen> oder gibts andere Gründe?
* Pragmatismus ?
* imun gegen "Optimitis"[1] ?
Woher weis der compiler, daß goto verpönt ist?
Fragen über Fragen!
Never touch a running system! ;)
[1] Optimitis: zwanghafter Optimierungswahn
Peter II schrieb:> goto bei C (nicht C++) zur Fehlerbehandlung ist üblich und sinnvoll.
Sehr richtig. "goto" ist immer dann sinnvoll, wenn es den Code einfacher
und übersichtlicher macht, zum Beispiel, wenn man aus verschachtelten
Schleifen heraus- oder eine Fehlerbehandlung anspringen will. Für
letzteres kennt C++ eigentlich die Exceptions -- aber wenn man die nicht
nutzen kann oder will, beispielsweise weil die Limits der Plattform
(think AVR) keine Exceptions hergeben, kann sogar dort ein "goto"
sinnvoll sein.
Wichtig ist allerdings, ein paar Regeln einzuhalten, auf die zum Teil
schon von Sebastian hingewiesen worden ist: nur innerhalb einer
Funktion, immer nur vorwärts, nach Möglichkeit nicht über mehrere
Bildschirmseiten springen und den Sprung an beiden Stellen ausführlich
dokumentieren -- idealerweise mit einer kurzen Begründung.
> wie gehts elegant ohne goto?> (Codebeispiel)
Dieser Code schreit danach, in mehrere Funktionen aufgesplittet zu
werden. Allein schon wegen der Übersicht.
Und wenn dann die conversionLoop() als Funktion bereit steht, dann
kannst du die goto's durch eben diesen Funktionsaufruf ersetzen.
Abgesehen davon: Ich denke schon, dass es sinnvolle Fälle für Goto gibt.
Aber selten, das ist ein richtiger Exot.
@ Stefan Us (stefanus)
>Dieser Code schreit danach, in mehrere Funktionen aufgesplittet zu>werden. Allein schon wegen der Übersicht.
Nicht zwingend. Aber der Coding Style ist, naja, verbesserungsfähig.
Wesentliche Kritikpunkte sind.
- goto braucht hier keiner
- Bei if(), for(), while() IMMER Klammern setzen, auch wenn nur eine
Anweisung drin steht
- ? Operator sehr sparsam einsetzen, wenn er WIRKLICH sinnvoll ist.
>Und wenn dann die conversionLoop() als Funktion bereit steht, dann>kannst du die goto's durch eben diesen Funktionsaufruf ersetzen.
Braucht man nicht mal.
>Abgesehen davon: Ich denke schon, dass es sinnvolle Fälle für Goto gibt.>Aber selten, das ist ein richtiger Exot.
EBEN! Aber das haben wir schon dutzendfach festgestellt.
Siehe Anhang. So sieht das DEUTLICH besser aus! Ausserdem war noch ein
kleiner Fehler drin, upp wurde nicht immer richtig zugewiesen! Auch das
move = 0 ist weiter oben deutlich sinnvoller platziert.
Wo braucht man bei strukturierter Programmierung ein "goto"?
https://de.wikipedia.org/wiki/Nassi-Shneiderman-Diagramm
Das C da einige Altlasten in Form von "break", "continue" und "goto"
mitschleppt, ist wohl der historischen Entwicklung geschuldet.
W.A. schrieb:> Wo braucht man bei strukturierter Programmierung ein "goto"?
Es geht nicht darum, ob man es braucht, sondern darum, ob es Fälle gibt,
in denen der Code dadurch übersichtlicher wird.
Schließlich braucht man ziemlich viel nicht. Man braucht z.B. auch keine
Datentypen, wenn man wie in Assembler einfach immer die Instruktion
nutzt, die die Daten eben passend interpretiert.
Nun machen Datentypen den Code praktisch immer übersichtlicher. Bei goto
gibt's nur wenige Fälle, aber es gibt sie.
> Das C da einige Altlasten in Form von "break", "continue" und "goto"> mitschleppt, ist wohl der historischen Entwicklung geschuldet.
Was für eine historische Entwicklung meinst du? Was ist denn in den
letzten 25 Jahren in C dazugekommen, das irgendwas an der Nützlichkeit
dieser Teile geändert hätte?
Rolf M. schrieb:> Was für eine historische Entwicklung meinst du?
Den verstärkten Trend zu strukturierter Programmierung.
> Was ist denn in den letzten 25 Jahren in C dazugekommen, das irgendwas an> der Nützlichkeit dieser Teile geändert hätte?
Welche Nützlichkeit meinst du?
Und wie kommst du gerade auf 25 Jahre? Das Kind von Brian W. Kernighan
und Dennis M. Ritchie lebt seit mittlerweile 38 Jahren.
Jeder C-Block im Sinne der strukturierten Programmierung ist ein
einzelnes Statement oder ein durch "{"..."}" zusammengefasste Gruppe von
Statements. Eine select()-case struktur mit ihrem break tanzt da
kräftig aus der Reihe. Bei strukturierter Programmierung mit
Funktionsblöcken, die genau einen definierten Eingang und Ausgang
haben ist jede Form von goto (goto, break, continue) kontraproduktiv.
So ein Bedürfniss nach einem Hinterausgang entspringt wohl eher der
Programmiererbequemlichkeit als dem Wunsch nach sauberer
Programmstruktur.
@ W.A. (Gast)
>Statements. Eine select()-case struktur mit ihrem break tanzt da>kräftig aus der Reihe.
Jain. Das C-switch ist auf break prinzipiell angewiesen, weil man jeden
Zweig damit abschließen muss, wenn man nicht absichtlich in den nächsten
reinfallen will. In Pascal, BASIC etc. braucht man das nicht, dort sind
die Zweige von vorn herein nicht "durchfallend".
> Bei strukturierter Programmierung mit>Funktionsblöcken, die genau einen definierten Eingang und Ausgang>haben ist jede Form von goto (goto, break, continue) kontraproduktiv.
Hmmm, jain. Ein break und continue ist in einer for/while Schleife hin
und wieder ganz praktisch, auch ohne Spaghetticode zu produzieren. Auch
mehrfache return in Funktionen sind bisweilen sinnvoll und praktisch und
beeinträchtigen die Codequalität nicht negativ.
>So ein Bedürfniss nach einem Hinterausgang entspringt wohl eher der>Programmiererbequemlichkeit als dem Wunsch nach sauberer>Programmstruktur.
C ist nicht perfekt, aber in der Praxis nun mal sehr breit etabliert. So
wie Windows, Verbrennungsmotoren und Schulzeugnisse ;-)
Ich bin ja nun kein Progger (obwohl ich programmiere)
aber wenn ich jede Funktion auf korrekte Funktion überprüfe gibt es
viele Fehlerfälle. Wenn ich diese in Verzweigungen einrücke finde ich
die Verschachtelungstiefe sehr hoch was irgendwan den Code auch
unübersichtlich in meinen Augen macht.
So ein goto error; kann da helfen.
Ich hatte in div. Kursen auch gelernt nicht mehrere Aussprungpunkte zu
machen
also Funktion Eingang -> ein Funktion Ausgang.
solche Konstrukte wie
funk()
{
if a=b return;
if a=c return;
if c!=b return;
return;
}
sollten vermieden werden (ich weiss schlechtes Beispiel kann grad nicht
besser, stellt euch das in großem Code vor)
da denke ich das hier wäre eben besser
funk()
{
if a=b goto raus;
if a=c goto raus;
if c!=b goto raus;
// hier ist noch was;
raus:
return;
}
Rolf M. schrieb:> Man braucht z.B. auch keine> Datentypen, wenn man wie in Assembler einfach immer die Instruktion> nutzt, die die Daten eben passend interpretiert.
Naja, ob du das nun implizit (in Assembler) oder explizit (in einer
Hochsprache) deklarierst: Dennnoch ist und bleibt es ein ein
Daten-Objekt mit einem zugehörigen Datentyp! Ob du dir das nun auf einem
Blatt Papier aufschreibst, dir im Kopf merkst oder dediziert
deklarierst, ist dabei egal.
Du solltest schon den Überblick haben und zu jedem Zeitpunkt "wissen",
wie dein zu bearbeitendes Datenobjekt "aufgebaut" ist, und welche
Operationen du darauf anwenden kannst.
Falk B. schrieb:> Das C-switch ist auf break prinzipiell angewiesen, weil man jeden> Zweig damit abschließen muss, wenn man nicht absichtlich in den nächsten> reinfallen will.
Das sag ich ja.
Warum ist im Sprachstandard nicht festgelegt, dass hinter jedem case
genau ein Statement/{..} folgt und fertig. Wegen dieser Inkonsequenz
meine ich, dass die C-switch Struktur ein Relikt aus Zeiten vor der
konsequenten strukturierten Programmierung ist und dass das break ein
(verstecktes) Goto über einen Hinterausgang darstellt.
Wegstaben V. schrieb:> Dafür gibt es Switch-Case Anweisungen.
nicht verstanden?
Joachim B. schrieb:> (ich weiss schlechtes Beispiel kann grad nicht> besser, stellt euch das in großem Code vor)Wegstaben V. schrieb:> Dafür gibt es Switch-Case Anweisungen. Schonmal ausprobiert?> http://www.c-howto.de/tutorial-verzweigungen-switch-case.html
ne nicht "ausprobiert" sondern nutze ich oft!
Ich habe einmal selber goto genutzt, nach dem wakeup in einer sleep Funk
wieder an den Anfang zu springen, wie sonst?
init-teil
einiges was nur einmal gemacht wird.
neustart:
anderes was nach jedem Neustart gemacht wird.
while(1)
{
viel code
//hier gings mal in den sleep
if wakeup goto neustart;
}
Mag sein, daß goto in der C-Welt seine Berechtigung hat. In der C++ Welt
braucht man es defakto nicht und falls ich jemals gefragt werden sollte
(was nicht passieren wird), würde ich für die Löschung aus dem Standard
stimmen. Das gleiche gilt für die Möglichkeit im switch das break
wegzulassen. In meiner Erfahrung ist das bisher immer ein Fehler
gewesen. Resourcen-Handling erledigt man automatisch mit RAII (nicht das
aus der Tube).
Mal ne Frage: wie würdet ihr ein 'intervall' switch-case implementieren?
Also falls x in[0,1] tue das, falls in [2,3[ dies, sonst jenes. Als
'endlosen' if-else Baum?
Oder wäre das u.U mit goto und einer Kommentarzeile eleganter?
Paul B. schrieb:> Wenn es statt "Goto" "HUPF" hieße, würden sich die Leute auch nicht so> gegen seine Verwendung sträuben.
Ist das die bayerische C Version?
switch = I_WOAS_NET
while = MOACH_WOAS
.
.
..
W.A. schrieb:> Warum ist im Sprachstandard nicht festgelegt, dass hinter jedem case> genau ein Statement/{..} folgt und fertig.
Weil es dann die Möglichkeit des fall through nicht gäbe. Aber genau
die wollten Kernigham und Ritchie anscheinend haben. Und oft ist sie
auch ganz praktisch. Z.B. immer dann wenn zwei (oder mehr) Fälle zu
exakt dem gleichen Code führen sollen.
Amüsante Diskussion.
Hatten wir schon vor 40 Jahren: Gleiche Argumente gleiche Borniertheit.
Niklaus Wirth baute damals seinen Pascal-Compiler natürlich ohne goto.
Nicht ganz.
Es gab doch eins, um aus einem völlig verwursteten Syntaxzweig
herauszukommen. Heute nimmt man dafür Excepions.
Niklaus Wirt:
Äquivalenz der Struktur von Daten und Programm.
Dem goto entspricht die Adresse also Pointer in C
PS.
Für Duden-Paule (pow):
Scheunen Sonndach ook
The D. schrieb:> Mag sein, daß goto in der C-Welt seine Berechtigung hat. In der C++ Welt> braucht man es defakto nicht und falls ich jemals gefragt werden sollte> (was nicht passieren wird), würde ich für die Löschung aus dem Standard> stimmen. Das gleiche gilt für die Möglichkeit im switch das break> wegzulassen. In meiner Erfahrung ist das bisher immer ein Fehler> gewesen.
Ich habe das durchaus schon mit Absicht benutzt, weil Alternativen immer
irgendwie umständlicher gewesen wären. Natürlich hab ich einen
entsprechenden Kommentar dazugeschrieben. Ich scheue mich nicht, sowas
in Fällen, wo es sinnvoll ist, auch zu verwenden. Sich dann irgendeine
umständliche und komplizierte Alternative einfallen zu lassen, nur weil
irgendwer behauptet, die in diesem Fall einfachste Lösung sei
grundsätzlich böse, finde ich albern.
> Resourcen-Handling erledigt man automatisch mit RAII (nicht das> aus der Tube).
Ich hab nie begriffen, warum das so heißt, aber ja, in C++ tut man das.
nanana schrieb:> Mal ne Frage: wie würdet ihr ein 'intervall' switch-case implementieren?> Also falls x in[0,1] tue das, falls in [2,3[ dies, sonst jenes. Als> 'endlosen' if-else Baum?> Oder wäre das u.U mit goto und einer Kommentarzeile eleganter?
Entweder - wenn das eine Option ist - entsprechende
Compiler-Erweiterungen nutzen (gcc kann z.B. switch/case auch mit
Wertebereichen), oder eben mit einer Reihe if/else (was ich in diesem
Fall bevorzugen würde). Warum sollte man dafür goto nutzen?
@ Rolf Magnus (rmagnus)
>Compiler-Erweiterungen nutzen (gcc kann z.B. switch/case auch mit>Wertebereichen),
Ist nicht portabel.
> oder eben mit einer Reihe if/else (was ich in diesem>Fall bevorzugen würde). Warum sollte man dafür goto nutzen?
Weil der Drang zum Frickeln bei einigen Menschen überaus hoch ist ;-)
(auch bei bezahlten Profis)
Warum hängen in Bussen immer diese roten Hämmerchen? Ich kennen
niemanden, der eins davon mal benutzt hätte. Ist das also nur auf den
Einfluss der Nothammerlobby zurückzuführen?
Goto ist der Nothammer der imperativen Programmierung.
Falk B. schrieb:> @ Rolf Magnus (rmagnus)>>>Compiler-Erweiterungen nutzen (gcc kann z.B. switch/case auch mit>>Wertebereichen),>> Ist nicht portabel.
Deshalb bevorzuge ich ja die Version mit if/else. Wobei ich sagen muss,
dass ich schon ziemlich lange kein C-Programm mehr geschrieben habe, das
auf was anderem als gcc übersetzt wurde. Dennoch tendiere ich dazu,
compilerspezifische Erweiterungen zu meiden.
Third E. schrieb:> Mir fällt ein spezieller Fall ein, wo goto bei Error Handling> tatsächlich Sinn macht:> Man könnte zwar den Aufräum-Code in eine separate Funktion packen, wie> im Code von Heinz L.. Dies hat aber zusätzliche Funktionsaufrufe zur> Folge, was Ausführungszeit und Kompilatgröße betrifft. Zumindest, wenn> der Aufräumcode von mehreren Stellen aus aufgerufen wird.> Ich habe mal einen Fall mitbekommen, wo es auf jedes eingesparte> Flash-Byte ankam. Wegen sehr großer verbauter Stückzahl war es nicht> möglich, einfach den nächstgrößeren µC zu verwenden.
Wenn's wirklich um jedes Byte Flash geht würd ich zuerst mal hergehen
und ein paar simple Routinen in ASM umsetzen. Damit gewinnt man
(angesichts der idiotisch miesen Optimierung des AVR-Compilers) mehr.
Heinz L. schrieb:> in ASM umsetzen. Damit gewinnt man> (angesichts der idiotisch miesen Optimierung des AVR-Compilers) mehr.
ist das so? hier meinen aber einige assembler Spezis anderes, so
schlecht soll der gcc nicht mehr sein!
Ich selber staune immer wie gut der gcc optimiert mit -0s
Selbst wenn ich denke ich könnte den Code verbessern/verkürzen indem ich
ihn verändere (2 Byte Flash Text optimiert gespart), logisch wurde der
kürzer, aber die Optimierung ist dann schlechter, aus 2 Byte - wird im
Code +6 bis +10 Byte.
Joachim B. schrieb:> ist das so? hier meinen aber einige assembler Spezis anderes, so> schlecht soll der gcc nicht mehr sein!
Schlecht ist er sicher nicht, aber in Assembler kann man oft doch noch
etwas optimieren. Ich habe mal den AES-Bootloader (AVR231) für ein
Projekt benutzt, allerdings musste wg. Kompatibilität zu anderen Geräten
da noch ein spezielles Kommunikations-Protokoll drübergelegt werden.
Ohne Ersatz einiger AES-Funktionen durch ASM-Routinen hätte ich keine
Chance gehabt, den BL in 1K Words unterzubringen. Nun bin ich nichtmal
so der AVR-Crack, d.h. AVR-Assembler war eher Fremdsprache (bisschen
anders, als PIC eben...), trotzdem hats am Ende doch schon viel
gebracht.
Also, besser, als ein mittelmäßiger ASM-Programmierer ist der GCC auch
nicht!
@Joachim B. (jar)
>Heinz L. schrieb:>> in ASM umsetzen. Damit gewinnt man>> (angesichts der idiotisch miesen Optimierung des AVR-Compilers) mehr.>ist das so?
Nein. Das ist nur die Meinung eines gesicht, namens- und ahnungslosen
Heinz.
Das ist modern . . .
>Ich selber staune immer wie gut der gcc optimiert mit -0s
Das tut er.
@ Thomas Elger (picalic)
>Schlecht ist er sicher nicht, aber in Assembler kann man oft doch noch>etwas optimieren.
Was aber in denn allerwenigsten Fällen wirklich sinnvoll und notwendig
ist!
>Ohne Ersatz einiger AES-Funktionen durch ASM-Routinen hätte ich keine>Chance gehabt, den BL in 1K Words unterzubringen.
Das ist so ein Ausnahmefall.
Joachim B. schrieb:> solche Konstrukte wie> funk()> {> if a=b return;> if a=c return;> if c!=b return;>> return;> }
Das Zauberwort heisst in diesem Fall "else if".
Ich habe in den letzten Jahren genau an einer Stelle GOTO eingesetzt,
und bin nach wie vor davon überzeugt, dass das eine der wenigen
Anwendungen war, wo es die Lesbarkeit des Codes deutlich erhöht und
gleichzeitig deutlich schneller ist:
Der Code stammt aus einer Mehrachs-Schrittmotor-Steuerung, bei der es
einen zeitkritischen Vermessungsmodus gibt. Wenn auf einer Achse die
Vermessung aktiv ist, wird die Bearbeitung der anderen Achsen
übersprungen.
z_measurement_g wird beim Starten der Vermessung gesetzt, um die anderen
Achsen zu blockieren.
Da ich grundsätzlich kein großer Freund von GOTO bin, habe ich mir
damals über Alternativen lange Gedanken gemacht.
- Organisation der Datenstrukturen Zn_g in einem Array
- Measurement-Modes für alle Achsen bitweise in eine gemeinsame Variable
mappen mit der man dann weiter arbeiten kann
Array: Der Implementierungsaufwand dafür wäre enorm gewesen, weil das
Feature erst später kam. Aber auch mit dem Array lässt sich das nicht
deutlich besser UND lesbar abbilden.
Mapping in gemeinsame Variable: Verschlechtert die Lesbarkeit des Codes
enorm, da dieses Mapping NUR für den Vermessungsmodus, aber nicht für
Fahrmodi, Initialisierungen o.ä. verwendet wird.
Die letzte Alternative wäre vor der Verarbeitung jeder Achse einen
if-Block mit 7 Bedingungen zu setzen, der meine Ansprüche an Lesbarkeit
überhaupt nicht erfüllt.
>Man springt auch nicht aus Prozeduren und Funktionen mit GOTO raus um>irgendwo anders hinzukommen,.....
das sollte inner Hochsprache eigentlich gar nicht möglich sein
GOTO zu verpönen hat schon etwas wie eine Glaubensfrage an sich.
Sicher lässt sich mit GOTOs ein absolut unverständlicher Spinnennetzcode
erzeugen. Das muss aber nicht so sein (siehe das Beispiel darüber).
Alle Programmzweige mit if.. then..else abzubilden kann sehr unlesbar
werden.
Strukturierte Programmierung fordert Blöcke mit einem Eingang und einem
Ausgang. Wenn ein GOTO zum Ende des Blocks springt, dann habe auch keine
Regelverletzung.
Bei sehr begrenzten Ressourcen kann hier durchaus eine Code-Einsparung
erzielt werden und der Code wird besser lesbar und damit besser wartbar.
Uns haben derartige Einsparungen schon mehrmals den Kopf gerettet.
Wie eingangs erwähnt ist es eigentlich wieder eine der Glaubensfragen.
Es wird immer Fanatiker für beide Richtungen geben. Mit Hirn verwendet
können GOTOs durchaus sinnvoll sein.
Thomas
Thomas schrieb:> Mit Hirn verwendet> können GOTOs durchaus sinnvoll sein.
Natürlich. Es gibt Anwendungen, bei denen es tatsächlich sinnvoll ist.
Bei der Fragestellung des TO:
Paul schrieb:> void hat aber die Eigenschaft, dort weiter zu machen, von wo es> aufgerufen wurde, es kehrt also zurück.> Wenn ich goto nutze, ergibt es teilweise eine totale> Unübersichtlichkeit.
ist die einzige richtige Antwort dann aber doch:
Kein goto verwenden. NIEMALS.
Oliver
Oliver S. schrieb:> Thomas schrieb:>> Mit Hirn verwendet>> können GOTOs durchaus sinnvoll sein.>> Natürlich. Es gibt Anwendungen, bei denen es tatsächlich sinnvoll ist.
da fällt mir mein relokatibler Code am PC1500 ein, hatte ich zwar in
Assembler gemacht aber auch JMP genauer branch (goto) benutzt.
Ich wollte ja eine Unteroutine aufrufen von verschiedenen Stellen.
Dummerweise ging jump subroutine oder jmp nicht weil das der Assembler
in absolute Adressen umsetzt und so relokatibler Code nicht
gewährleistet ist.
Ergo habe ich im PC Register geschaut gesichert das auf den Stack mit
Korrektur geschrieben und mit +branch vorwärts oder -branch rückwärts
(goto) hingehüpft, mit rts konnte ich immer wieder an die richtige
Stelle zurück egal wo sie im Speicher lag.
Frank B. schrieb:> Der Code stammt aus einer Mehrachs-Schrittmotor-Steuerung, bei der es> einen zeitkritischen Vermessungsmodus gibt. Wenn auf einer Achse die> Vermessung aktiv ist, wird die Bearbeitung der anderen Achsen> übersprungen.> z_measurement_g wird beim Starten der Vermessung gesetzt, um die anderen> Achsen zu blockieren.> Da ich grundsätzlich kein großer Freund von GOTO bin, habe ich mir> damals über Alternativen lange Gedanken gemacht.> - Organisation der Datenstrukturen Zn_g in einem Array> - Measurement-Modes für alle Achsen bitweise in eine gemeinsame Variable> mappen mit der man dann weiter arbeiten kann
Also,
die Variable z_measurement_g einzuführen ist okay, aber die bevorzugte
Achse so zu speichern nicht?
zu deinem Code:
ich hab dein struct mal motion genannt (keine Ahnung wie es heist) und
es ist als typedef angelegt. Deswegen keine structs im code.
ohne goto und schön übersichtlich. Auf Kosten von 7 Zeigern.
PS: wer fehler findet darf sie gerne aufzeigen ohne Flamen. Ich
programmier so selten C da können kleinigkeiten schon mal durchrutschen.
Bei den sizeof Geschichten bin ich mit nicht sicher ob das so richtig
ist.
Frank B. schrieb:> Ich habe in den letzten Jahren genau an einer Stelle GOTO eingesetzt,> und bin nach wie vor davon überzeugt, dass das eine der wenigen> Anwendungen war, wo es die Lesbarkeit des Codes deutlich erhöht und> gleichzeitig deutlich schneller ist:
[Ganz viel schlimmer Mist gelöscht]
Man, Leute, lernt mal wieder einfache, boolsche Logik, dann muss man
auch keine Goto- und continue-Wüsten schreiben. Nichts für ungut, aber
dieses Beispiel ist wirklich als Negativ-Beispiel für ein Lehrbuch
geeignet.
Und nun die Lösung: Punkt eins ist immer, sich selbst zu verstehen was
man will. Was willst Du mit Deinem Code?
a.) Wenn z_measurement_g == FALSE ist, alle Schrittmotoren aufrufen.
b.) Wenn z_measurement_g == TRUE ist, nur einen bestimmten.
Also, ganz einfach:
Oh je, das war natürlich Blödsinn mit dem Zeiger. Es werden im Code
drüber natürlich Kopien angelegt.
Der Code geht natürlich auch, aber hier noch mal die Änderung mit
Zeigern:
Paul schrieb:> Wenn ich goto nutze, ergibt es teilweise eine totale> Unübersichtlichkeit. Ist schlecht nachzuvollziehen wo es weiter geht.> Im Netz wird da von gesprochen, das es verpöönt ist nichrr genutzt> werden soll.> Was nutz ihr bei solchen Sachen?
Eigentlich ist es ja so unsäglich EINFACH: Anstatt sich in Situationen,
wo ein simples GOTO angesagt ist, um irgendwelche krummen
Ersatz-Ausdrücke zu bemühen, nimmt man schlichtweg ein Goto und gut ist
es.
Üble Beispiele aus der Welt der C-Programmiere sind sowas:
for (;;;) blabla...;
while (1) blabla...;
Das sind alles entartete Konstrukte, weil sie eigentlich für ganz andere
Einsatzfälle in die Sprache aufgenommen wurden und hier eben nur durch
leider nicht unzulässige Parameter vergewaltigt wurden. Für solche Fälle
ist das Setzen einer Merke und GOTO die sauberste, einfachste, lesbarste
und stilvollste Methode.
Historisch war das verpönen von GOTO einfach nur dem Umstand geschuldet,
daß die allermeisten Hobby-Programmierer an das damalige BASIC gewöhnt
waren, wo GOTO schlichtweg unerläßlich war, da das damalige BASIC streng
zeilennummerorientiert war. Ich sehe da Parallelen zur menschlichen
Gesellschaft in prähistorischen Zeiten, wo nomadisierende Völkerstämme
Verpön-Regeln aufgestellt hatten, um eine Verbrüderung mit
ortsansässigen Bauern zu verhindern. Und dreitausend Jahre später labern
deren Nachfahren immer noch dieselben inzwischen obsolet gewordenen
Regeln daher - aus schierem Unverständnis.
Beim Lesen deines Eröffnungs-Posts beschleicht mich jedoch der Gedanke,
daß du versuchst, per Goto von einer Funktion in eine andere zu springen
- und das wäre dann wirklich ganz schlechter Code, falls überhaupt
zulässig.
W.S.
W.S. schrieb:> Üble Beispiele aus der Welt der C-Programmiere sind sowas:> for (;;;) blabla...;> while (1) blabla...;>> Das sind alles entartete Konstrukte, weil sie eigentlich für ganz andere> Einsatzfälle in die Sprache aufgenommen wurden und hier eben nur durch> leider nicht unzulässige Parameter vergewaltigt wurden. Für solche Fälle> ist das Setzen einer Merke und GOTO die sauberste, einfachste, lesbarste> und stilvollste Methode.
Der Beitrag kommt vier Tage zu spät. Gut ist er aber trotzdem. :D
W.S. schrieb:> Üble Beispiele aus der Welt der C-Programmiere sind sowas:> for (;;;) blabla...;> while (1) blabla...;
Mein Favorit ist ja noch immer:
while("my guitar gently weeps") ...
Aber auch eine Endlosschleife ist noch immer eine Schleife.
Den C-Kontrollstrukturen sieht man (sofern man es nicht sehr drauf
anlegt...) auf den ersten Blick an was sie machen und wo es weitergeht
und die Verzweigungen ergeben sich direkt aus dem lokalen Kontext.
Bei einem goto weiß man nur, dass es irgendwo anders weitergeht, das
Label könnte aber sonstwo stehen.
> Für solche Fälle ist das Setzen einer Merke und GOTO die sauberste, einfachste,
lesbarste und stilvollste Methode.
Ich bin ja dafür es rekursiv zu lösen, funktionale Programmierung ist
immerhin recht elegant und mit Endrekursion macht auch eine
Endlosschleife keine Probleme...
W.A. schrieb:> Welche Nützlichkeit meinst du?
Die, von der du behauptest, sie sei aufgrund "historischer Entwicklung"
nicht mehr gegeben.
> Und wie kommst du gerade auf 25 Jahre?
Kein spezieller Grund. Ein viertel Jahrhundert schien mir nur lang
genug. Es ist auch ungefähr die Zeit, seit der C genormt ist.
> Bei strukturierter Programmierung mit Funktionsblöcken, die genau einen> definierten Eingang und Ausgang haben ist jede Form von goto (goto,> break, continue) kontraproduktiv.
Mangels eines besseren Konstrukts kann es aber trotzdem sinnvoll sein.
Wegstaben V. schrieb:> Rolf M. schrieb:>> Man braucht z.B. auch keine>> Datentypen, wenn man wie in Assembler einfach immer die Instruktion>> nutzt, die die Daten eben passend interpretiert.>> Naja, ob du das nun implizit (in Assembler) oder explizit (in einer> Hochsprache) deklarierst: Dennnoch ist und bleibt es ein ein> Daten-Objekt mit einem zugehörigen Datentyp!
Es geht hier um in Programmiersprachen eingebaute Konzepte, nicht darum,
was ich implizit noch so außenrum mache.
> Ob du dir das nun auf einem Blatt Papier aufschreibst, dir im Kopf merkst> oder dediziert deklarierst, ist dabei egal.
Egal? Naja, also ich find's schon ziemlich praktisch, dass dieses
Konzept in der Sprache integriert ist und ich mir die Typen nicht extra
auf einem Blatt Papier aufschreiben muss. Und dass der Compiler die
Chance hat, da auch drüber zu schauen.
W.S. schrieb:> Üble Beispiele aus der Welt der C-Programmiere sind sowas:> for (;;;) blabla...;> while (1) blabla...;>> Das sind alles entartete Konstrukte, weil sie eigentlich für ganz andere> Einsatzfälle in die Sprache aufgenommen wurden und hier eben nur durch> leider nicht unzulässige Parameter vergewaltigt wurden.
Dann erkläre mal, warum for so definiert ist, dass man die Bedingung
weglassen kann, wenn nicht genau, um eine Schleife ohne diese machen zu
können.
> Für solche Fälle ist das Setzen einer Merke und GOTO die sauberste,> einfachste, lesbarste und stilvollste Methode.
Was soll daran besser sein als es als das zu definieren, was es ist:
Eine Schleife?
> Historisch war das verpönen von GOTO einfach nur dem Umstand geschuldet,> daß die allermeisten Hobby-Programmierer an das damalige BASIC gewöhnt> waren, wo GOTO schlichtweg unerläßlich war, da das damalige BASIC streng> zeilennummerorientiert war.
Ich glaube, umgekehrt wird ein Schuh draus: Dass es goto in C überhaupt
gibt, ist den genannten Umständen geschuldet.
Rolf M. schrieb:> Dann erkläre mal, warum for so definiert ist, dass man die Bedingung> weglassen kann, wenn nicht genau, um eine Schleife ohne diese machen zu> können.
Nun, man hat gerade in C durchaus die große Freiheit sich daneben zu
benehmen, aber auch dann, wenn es nicht explizit verboten ist, sich
selbst in die Suppe zu spucken oder andern Leuten auf den Türvorleger zu
scheißen - so gilt dies unter zivilisierten Leuten als eher
unschicklich, gelle?
W.S.
W.S. schrieb:> Nun, man hat gerade in C durchaus die große Freiheit sich daneben zu> benehmen, aber auch dann, wenn es nicht explizit verboten ist, sich> selbst in die Suppe zu spucken oder andern Leuten auf den Türvorleger zu> scheißen - so gilt dies unter zivilisierten Leuten als eher> unschicklich, gelle?
Wie auch goto. ;-)
Heinz L. schrieb:> Wenn's wirklich um jedes Byte Flash geht würd ich zuerst mal hergehen> und ein paar simple Routinen in ASM umsetzen. Damit gewinnt man> (angesichts der idiotisch miesen Optimierung des AVR-Compilers) mehr.
Wie Yalu bereits in einem Thread mit dem Assembler-Fan "Moby" bewiesen
hat, sind solche Aussagen eine Mischung aus dummen Vorurteilen und
grobem Unfug. Sogar bei trivialen, kleinen Programmen optimiert der
AVR-GCC in der Regel besser als ein erfahrener Assembler-Programmierer.
Sheeva P. schrieb:> Sogar bei trivialen, kleinen Programmen optimiert der> AVR-GCC in der Regel besser als ein erfahrener Assembler-Programmierer.
Das ist ein genauso dummes Vorurteil, nur in die andere Richtung!
Wie ich weiter oben schon schrieb, bin ich kein erfahrener
AVR-Assembler-Programmierer und habe trotzdem ein gutes Stück
Optimierungspotential gefunden.
Ich denke, dass es auch viel mit Geschmack zutun hat. Ich persönlich
nehme i.d.R. nach der Initialisierung vom µC eine while(1)-Schleife. Die
werden automatisch so eingerückt wie andere Schleifen oder allgemein
{}Blöcke. Bei einem Goto ist dies nicht der Fall und finde ich
PERSÖNLICH unübersichtlicher.
Der unterschied besteht eigentlich nur darin, dass man statt
1
while(1){
2
// Argument für Goto
3
// Argument gegen Goto
4
// Beleidigungen austauschen
5
}
auch
1
Anfang:
2
// Argument für Goto
3
// Argument gegen Goto
4
// Beleidigungen austauschen
5
gotoAnfang;
schreiben kann. Letztendlich macht der Compiler auch nur ein Goto
daraus, ob Schleife oder Sprung. Der resultierende Code sollte also der
gleiche sein.
Bei manchen Dingen bringt es einfach nichts zu diskutieren, weil niemand
wirklich Recht haben kann.
Meine Meinung
Thomas E. schrieb:> Sheeva P. schrieb:>> Sogar bei trivialen, kleinen Programmen optimiert der>> AVR-GCC in der Regel besser als ein erfahrener Assembler-Programmierer.>> Das ist ein genauso dummes Vorurteil, nur in die andere Richtung!
Nein, das ist das, was Yalu damals nachgewiesen hat: der Proband hatte
eine ziemlich ausgeklügelte Assemblervorlage hingelegt, die sehr
intensiv nur auf einen kleinen, sehr überschaubaren Spezialfall
getrimmt war.
Dennoch war es Yalu gelungen, letztlich ein C-Programm zu zimmern,
dass dieses unterbieten konnte.
> Wie ich weiter oben schon schrieb, bin ich kein erfahrener> AVR-Assembler-Programmierer und habe trotzdem ein gutes Stück> Optimierungspotential gefunden.
Vor wieviel Jahren war das? Wenn es drei Jahre oder mehr her ist,
kannst du das mit dem heutigen Compiler bei weitem nicht mehr
vergleichen. Seit Johann (Georg Lay) da mal Hand angelegt hat, ist
der Compiler deutlich effizienter geworden (sprich, ab ca. GCC 4.7).
Der Controller kennt eh nur JMP und JSR.
Die Regeln zum Coding Style sind Qualitätsmaßnahmen. Qualitätsmanagement
dient dazu, die Arbeit vom Menschen zu entkoppeln. Wenn Du tot umfällst,
kann ein anderer Deinen Code weiterpflegen. Der kann dann auch in
Indien, China oder auf dem Mars sitzen. Das geht nicht, wenn jeder nach
seinen eigenen Regeln spielt.
Michael S. schrieb:> Die werden automatisch so eingerückt wie andere Schleifen> oder allgemein {}Blöcke. Bei einem Goto ist dies nicht der> Fall und finde ich PERSÖNLICH unübersichtlicher.
Nicht nur du. Das ist ja der Grund, warum man Goto nicht verwenden soll.
Bei einer Schleife kann selbst die dumme IDE erkennen, wo sie anfängt
und wo sie aufhört, ein Programmierer erst Recht, spätestens mit
Einrückung.
Bei Goto weiß man dagegen nicht, wo es hinspringt. Das heißt, man weiß
noch nichtmal, in welcher Richtung man suchen soll, und deshalb ist es
zu vermeiden.
Michael S. schrieb:> Letztendlich macht der Compiler auch nur ein Goto daraus,> ob Schleife oder Sprung.
Letztendlich macht der Compiler aus dem Programm Maschinencode. Das ist
aber kein Argument dafür, in Maschinencode zu programmieren. (Das habe
ich aus Interesse mal gemacht, und es ist umständlich.) Hochsprachen
wurden dafür entwickelt, einfacher (verständlich) zu sein und
Konstrukte, wie Jump, durch übersichtliche Strukturen zu verdecken. Das
zu umgehen, indem man in Hochsprachen einen Sprungbefehl benutzt, ist in
nahezu 100% der Fälle sinnlos.
Bitwurschtler schrieb:> jump_table[value]();
Bei der Frage, ob man goto verwenden sollte, geht es aber um Code
innerhalb einer Funktion. Mit gcc sähe das dann so aus:
Dussel schrieb:> Bei Goto weiß man dagegen nicht, wo es hinspringt. Das heißt, man weiß> noch nichtmal, in welcher Richtung man suchen soll, und deshalb ist es> zu vermeiden.
Ich weiß ja nicht mit welchen IDEs ihr hier alle arbeitet aber meine IDE
ist in der Lage den Quellcode nach beliebigen Strings zu durchsuchen.
Auch über mehrere Quellcodedateien hinweg. Da herauszufinden wohin ein
goto führt ist also heute wirklich kein Kunstwerk mehr...
Clemens L. schrieb:> Bitwurschtler schrieb:>> jump_table[value]();> Oder vielleicht doch besser switch() ...
switch iss aber keine Sprungtabelle da letztere ohne Bedingungsprüfung
auskommt, aber einen Befehlssatz mit relativen Sprung vorraussetzt.
In einem meiner ersten Programme, das ich damals(TM) unter Pascal
gefrickelt habe, war ich so begeistert von der Macht der Sprünge.
Ich habe GOTOs derart exzessiv/kreuzweise/vor-/rückwärts verwendet,
sodass ich am Ende nicht mehr den Überblick hatte.
GOTO = Teufelszeug
kast schrieb:> In einem meiner ersten Programme, das ich damals(TM) unter Pascal
....
> sodass ich am Ende nicht mehr den Überblick hatte.
Der Überblicksverlust ist bei "erste Programme" völlig normal und nicht
einzig dem GOTO geschuldet.
Schau dir mal die Pointer-Orgien eines C-Rookies an der cool wirken
will. Oder das ekstatische Überladen im Code eines OOP-Novizen.
Genies erklären einfach das Chaos zur Ordnung:
https://en.wikipedia.org/wiki/International_Obfuscated_C_Code_Contest#Examples
Bitwurschtler schrieb:> Genies erklären einfach das Chaos zur Ordnung:
Du solltest da schon einen Smiley setzen.
Der IOCCC ist bestimmt für irgendwas gut, aber jedenfalls nicht dafür,
dass jemand jemals behauptet hätte, sowas wäre der zu bevorzugende
Programmierstil eines C-Programmierers. ;-)
Aber ja, eine gewisse Genialität benötigt man, um dort erfolgreich zu
sein. Mit reinem „Anfänger-Chaos“ wird man da eher kein Glück bei der
Jury haben …
Jörg W. schrieb:> Bitwurschtler schrieb:>> Genies erklären einfach das Chaos zur Ordnung:>> Du solltest da schon einen Smiley setzen.
Ja, so war das auch gedacht, als schelmische Bemerkung mit einem Schuß
Chuzpe - nicht völlig ernst aber auch nicht völlig Banane. Man könnte es
auch so formulieren:
"Only fools and geniuses uses "Goto" " };-)
M. K. schrieb:> Ich weiß ja nicht mit welchen IDEs ihr hier alle arbeitet aber meine IDE> ist in der Lage den Quellcode nach beliebigen Strings zu durchsuchen.> Auch über mehrere Quellcodedateien hinweg. Da herauszufinden wohin ein> goto führt ist also heute wirklich kein Kunstwerk mehr...
Und bei einem richtig tollen Spaghetticode behältst du mit der
Suchfunktion den Überblick? ;-)
Hugo schrieb:> Und bei einem richtig tollen Spaghetticode behältst du mit der> Suchfunktion den Überblick? ;-)
Dass man keinen Spaghetticode fabrizieren soll, ist doch nun wirklich
jedem klar.
Aber man muss nun auch nicht so tun, als ob jede Verwendung des
Wortes “goto” automatisch diesen verursachen würde.
Wenn jemand unbedingt nach „reiner Lehre“ arbeiten möchte, dann möge
er bitte auch noch „break“ (aus einer Schleife), „continue“ und
„return“ (ausgenommen exakt am Ende der Funktion, um einen Wert
zurückzugeben) aus seinem Wortschatz verbannen. Das sind alles nur
„verkappte goto“s. Ob der Code von solcherart Dogmen wirklich besser
lesbar wird, wage ich zu bezweifeln.
Ansonsten: Donald Knuth wurde ja oben schon genannt, mit seinem
“Structured Programming with Go To”, als Replik auf Dijkstras (aus
Knuth's Sicht) Dogmen.
Jörg W. schrieb:> Dass man keinen Spaghetticode fabrizieren soll, ist doch nun wirklich> jedem klar.>> Aber man muss nun auch nicht so tun, als ob jede Verwendung des> Wortes “goto” automatisch diesen verursachen würde.
Das ist mir schon klar. Ich verteufele das GOTO ja auch nicht generell.
In manchen Fällen ist es schon angebracht. Ich glaube, da sind wir uns
einig, daß es durchaus solche Situationen gibt.
Jörg W. schrieb:> Wenn jemand unbedingt nach „reiner Lehre“ arbeiten möchte, dann möge> er bitte auch noch „break“ (aus einer Schleife), „continue“ und> „return“ (ausgenommen exakt am Ende der Funktion, um einen Wert> zurückzugeben) aus seinem Wortschatz verbannen. Das sind alles nur> „verkappte goto“s.
Mit dem Unterschied, dass klar ist, wo die hinspringen. Den Überblick,
in welcher Schleife oder Funktion man sich befindet, sollte man im
Allgemeinen schon haben.
Jörg W. schrieb:> Hugo schrieb:>> Ich glaube, da sind wir uns einig, daß es durchaus solche Situationen>> gibt.>> Ist eigentlich ein schönes Schlusswort für den Thread. ;-)
So weit waren wir vor einem Monat schon. :-)
Dussel schrieb:> Mit dem Unterschied, dass klar ist, wo die hinspringen. Den Überblick,> in welcher Schleife oder Funktion man sich befindet, sollte man im> Allgemeinen schon haben.
Den Überblick sollte man auch bei Verwendung von goto haben und wenn man
kein Spagetticode damit fabriziert ist der Überblick auch recht gut zu
halten.
Jörg W. schrieb:> Vor wieviel Jahren war das? Wenn es drei Jahre oder mehr her ist,> kannst du das mit dem heutigen Compiler bei weitem nicht mehr> vergleichen. Seit Johann (Georg Lay) da mal Hand angelegt hat, ist> der Compiler deutlich effizienter geworden (sprich, ab ca. GCC 4.7).
Ist noch nicht so lange her - gegen Ende des letzten Jahres, unter Atmel
Studio 7.
Welche Version des Compilers genau kann ich grad nicht sagen, bin nicht
im Büro.
Dussel schrieb:> Jörg W. schrieb:>> Hugo schrieb:>>> Ich glaube, da sind wir uns einig, daß es durchaus solche Situationen>>> gibt.>>>> Ist eigentlich ein schönes Schlusswort für den Thread. ;-)> So weit waren wir vor einem Monat schon. :-)
Und immer noch gibts kein Beispiel für solch eine Situation...
Oliver
Oliver S. schrieb:> Und immer noch gibts kein Beispiel für solch eine Situation...
Die gibt es massig. Schau dir einfach die Kernels von *BSD oder
Linux an.
Oliver S. schrieb:> Und immer noch gibts kein Beispiel für solch eine Situation...
Ach?
Wir sind hier im µC-Forum, ja?
Bei unseren Programmen (sprich Firmware) passiert es eigentlich nie, daß
main mal zurückkehrt. Blöderweise bestehen einige Toolchains darauf, daß
main vom Typ int sein soll und nicht void sein darf. Und ne int function
hat gefälligst auch nen Integer zu hinterlassen - auch wenn das vom
Programmierer garnicht beabsichtigt ist.
Was also schjreibt der geneigte Programmierer?
1
intmain(void)
2
{// initialisierungen
3
....
4
5
while(1)
6
{// irgendwelcher Inhalt
7
...
8
}
9
return0;
10
}
weil er sonst vom Compiler angepfiffen wird. Selber schon unzählige Male
erlebt.
Wie also geht's besser? So:
1
intmain(void)
2
{// initialisierungen
3
....
4
5
elleweil:
6
// irgendwelcher Inhalt
7
...
8
gotoelleweil;
9
}
Bei diesem Konstrukt merkt der Compiler endlich (!), daß es nie und
nimmer zurückgeht und hält die Fresse.
Eine andere Baustelle sind Funktionen, wo im Fehlerfalle nicht einfach
abgebrochen, sondern auch noch aufgeräumt werden muß. Etwa so:
1
intblabla(.....)
2
{intretcode;
3
4
Aktion1...// z.B. File öffnen
5
retcode=1;
6
if(!Kondition1())gotoraus_hier;
7
8
Aktion2...// z.B. parsen
9
retcode=2;
10
if(!Kondition2())gotoraus_hier;
11
12
Aktion2...// z.B. noch ne Datei öffnen
13
nochmalsowaswieoben
14
15
retcode=Is_OK;
16
MachSonstwas...
17
18
raus_hier:
19
RäumeAuf,SchließeAb...
20
returnRetCode;
21
}
Natürlich könnte man das alles ohne goto's nur mit if's schachteln oder
das Aufräumen und Abschließen bei jeder fehlgeschlagenen Kondition
separat hinschreiben, aber das ist erstens aufwendiger, zweitens
schlechter lesbar und drittens müßte man bei jeder Änderung am
Aufräumcode selbigen n-mal ändern.
Es ist ja nicht so, daß man goto an jeder Ecke dreimal braucht, aber es
generell zu verteufeln ist schlichtweg engstirnig.
W.S.
@ W.S. (Gast)
>main mal zurückkehrt. Blöderweise bestehen einige Toolchains darauf, daß>main vom Typ int sein soll und nicht void sein darf.
Ist halt so.
>Was also schjreibt der geneigte Programmierer?>int main (void)>{ // initialisierungen> ....> while (1)> { // irgendwelcher Inhalt> ...> }> return 0;>}>weil er sonst vom Compiler angepfiffen wird. Selber schon unzählige Male>erlebt.
Na dann schreib es doch einfach und vergiss die Sache! Mein Gott, das
sind Luxusprobleme!
>Wie also geht's besser? So:
Besser? Murks^3!
>Eine andere Baustelle sind Funktionen, wo im Fehlerfalle nicht einfach>abgebrochen, sondern auch noch aufgeräumt werden muß. Etwa so:
Dies allgemeine Aussage hatten wir schon dutzendfach. Ein WIRKLICH
überzeugendes Beispiel aus der PRAXIS fehlt immer noch. Die Skizze
reicht nicht.
>Es ist ja nicht so, daß man goto an jeder Ecke dreimal braucht, aber es>generell zu verteufeln ist schlichtweg engstirnig.
Das hatten wir schon x-fach.
Du klingst recht fanatisch - und Fanatiker kann man mit keiner Wahrheit
überzeugen.
Also wenn du dir Augen und Ohren zuhältst und dann rufst "ich kann keine
Argumente sehen noch hören", dann bleib einfach dabei.
W.S.
W.S. schrieb:> Was also schjreibt der geneigte Programmierer?> [Zu viele Zitatzeilen]> weil er sonst vom Compiler angepfiffen wird. Selber schon unzählige Male> erlebt.
Das habe ich gerade mit XCode ausprobiert und der Compiler sagt gar
nichts. Das 'Schlimmste', das ich in dem Fall erlebt habe, war eine
Warnung 'Unreachable Statement'. Wenn du so dünnhäutig bist, dass dich
eine Warnung so fertig macht, kannst du auch Goto verwenden, aber das
ist absolut nicht die Regel.
W.S. schrieb:> Was also schjreibt der geneigte Programmierer?> int main (void)> { // initialisierungen> ....>> while (1)> { // irgendwelcher Inhalt> ...> }> return 0;> }>> weil er sonst vom Compiler angepfiffen wird. Selber schon unzählige Male> erlebt.>> Wie also geht's besser? So:> int main (void)> { // initialisierungen> ....>> elleweil:> // irgendwelcher Inhalt> ...> goto elleweil;> }>> Bei diesem Konstrukt merkt der Compiler endlich (!),
Ist schon wieder Märchenstunde mit W.S?
Erstens ist mir noch kein Compiler begegnet der mich wegen meiner int
main(void) angepfiffen hat, selbst auf der schärfsten Warnstufe nicht
und zweitens merkt er bei while(1) sehr wohl daß die Schleife unendlich
ist, die beiden Beispiele oben sind diesbezüglich vollkommen äquivalent,
das goto ist überflüssig, mit while(1) gehts genauso und sieht schöner
aus.
begin dummy text
Bitte reduzieren Sie die Anzahl der Zitatzeilen. Bitte reduzieren Sie
die Anzahl der Zitatzeilen. Bitte reduzieren Sie die Anzahl der
Zitatzeilen. Bitte reduzieren Sie die Anzahl der Zitatzeilen. Bitte
reduzieren Sie die Anzahl der Zitatzeilen. Bitte reduzieren Sie die
Anzahl der Zitatzeilen. Bitte reduzieren Sie die Anzahl der Zitatzeilen.
Bitte reduzieren Sie die Anzahl der Zitatzeilen. Bitte reduzieren Sie
die Anzahl der Zitatzeilen. Bitte reduzieren Sie die Anzahl der
Zitatzeilen. Bitte reduzieren Sie die Anzahl der Zitatzeilen. Bitte
reduzieren Sie die Anzahl der Zitatzeilen. Bitte reduzieren Sie die
Anzahl der Zitatzeilen. Bitte reduzieren Sie die Anzahl der Zitatzeilen.
Bitte reduzieren Sie die Anzahl der Zitatzeilen. Bitte reduzieren Sie
die Anzahl der Zitatzeilen. Bitte reduzieren Sie die Anzahl der
Zitatzeilen.
end dummy text
Jörg W. schrieb:> Nein, das ist das, was Yalu damals nachgewiesen hat: der Proband hatte> eine ziemlich ausgeklügelte Assemblervorlage hingelegt, die sehr> intensiv nur auf einen kleinen, sehr überschaubaren Spezialfall> getrimmt war.>> Dennoch war es Yalu gelungen, letztlich ein C-Programm zu zimmern,> dass dieses unterbieten konnte.
Und mit diesem einen Beispiel hat er nachgewiesen, dass das "in der
Regel" so ist?
soul e. schrieb:> Der Controller kennt eh nur JMP und JSR.>> Die Regeln zum Coding Style sind Qualitätsmaßnahmen. Qualitätsmanagement> dient dazu, die Arbeit vom Menschen zu entkoppeln. Wenn Du tot umfällst,> kann ein anderer Deinen Code weiterpflegen.
Oder wenn du in Urlaub gehst und nach der Rückkehr immer noch an dem
Code arbeiten musst.
W.S. schrieb:> Bei unseren Programmen (sprich Firmware) passiert es eigentlich nie, daß> main mal zurückkehrt. Blöderweise bestehen einige Toolchains darauf, daß> main vom Typ int sein soll und nicht void sein darf.
Das ist in ISO C ja auch so vorgeschrieben.
> Bei diesem Konstrukt merkt der Compiler endlich (!), daß es nie und> nimmer zurückgeht und hält die Fresse.
Aha, du nutzt also goto in diesem Fall nur, um auf "geschickte" Weise
die Regeln zu umgehen, damit du es dir sparen kannst, ein extra "return
0;" in die Tasten zu hämmern...
> Eine andere Baustelle sind Funktionen, wo im Fehlerfalle nicht einfach> abgebrochen, sondern auch noch aufgeräumt werden muß. Etwa so:> int blabla (.....)> { int retcode;>> Aktion1... // z.B. File öffnen> retcode=1;> if (!Kondition1()) goto raus_hier;>> Aktion2... // z.B. parsen> retcode=2;> if (!Kondition2()) goto raus_hier;>> Aktion2... // z.B. noch ne Datei öffnen> nochmal sowas wie oben>> retcode=Is_OK;> MachSonstwas...>> raus_hier:> RäumeAuf, SchließeAb...> return RetCode;> }
Für mich ist eine Erweiterung dieses Falles erst so richtig ein Grund,
goto zu nutzen. Meist muss man schließlich nicht in jedem Fehlerfall das
selbe Cleanup machen. Wenn z.B. das File nicht geöffnet werden konnte,
darf ich auch nicht versuchen, es zu schießen. Ich muss also quasi in
umgekehrter Reihenfolge der Aktionen mehrere Cleanup-Aktionen
durchführen, aber nur den Teil davon, zu dem auch die Aktionen
erfolgreich waren.
> Es ist ja nicht so, daß man goto an jeder Ecke dreimal braucht, aber es> generell zu verteufeln ist schlichtweg engstirnig.
Das sehe ich ganz genauso.
Bernd K. schrieb:> begin dummy text> Bitte reduzieren Sie die Anzahl der Zitatzeilen.> [...]
Gibt es einen speziellen Grund, warum du das X mal postest, statt es
einfach zu tun?
Dussel schrieb:> Das 'Schlimmste', das ich in dem Fall erlebt habe, war eine> Warnung 'Unreachable Statement'. Wenn du so dünnhäutig bist, dass dich> eine Warnung so fertig macht, kannst du auch Goto verwenden, aber das> ist absolut nicht die Regel.
Das erste was uns eingeprügelt wurde von unserem Info-Prof:
There is no reason to ignore warnings.
Und IMO hat er Recht, daher kommt beim Compiler auch immer die -Wall und
das liebe -Werror zum Einsatz
Dussel schrieb:> Das 'Schlimmste', das ich in dem Fall erlebt habe, war eine> Warnung 'Unreachable Statement'.
Reicht das nicht?
Entweder gibt es vom Compiler keine Fehler und Warnungen oder es liegt
eben was im Argen - was auch immer. Willst du bei jedem Compilerlauf
überprüfen, ob genau diese Warnung nun tatsächlich ignorabel ist oder
ist dir das schnurz?
Hier hab ich es also offensichtlich mit Leuten zu tun, die aus schierer
Abneigung gegen ein simples goto selbst Compilerwarnungen in Kauf
nehmen.
Ist mir völlig unverständlich. Ich pack das in die Schublade
"Fanatismus".
W.S.
M. K. schrieb:> Das erste was uns eingeprügelt wurde von unserem Info-Prof:>> There is no reason to ignore warnings.
Das hätte ich eher von einem Deutschen erwartet. Wir gelten doch als
regelhörig. :-)
M. K. schrieb:> Und IMO hat er Recht, daher kommt beim Compiler auch immer die -Wall und> das liebe -Werror zum Einsatz
Man soll sie ja auch nicht ignorieren - 'wird schon passen' - sondern
sie sich anschauen und überlegen, ob man 'Gegenmaßnahmen' treffen muss.
Wenn ich aber eine Endlosschleife schreibe, die auch eine Endlosschleife
sein soll, ist mir klar, dass Befehle dahinter nicht erreicht werden.
Was ist denn dann der Unterschied zwischen einem Fehler und einer
Warnung, wenn man eine Warnung wie einen Fehler behandeln soll?
W.S. schrieb:> Hier hab ich es also offensichtlich mit Leuten zu tun, die aus schierer> Abneigung gegen ein simples goto selbst Compilerwarnungen in Kauf> nehmen.
Wie ich gerade schon schrieb, habe ich keine Warnung bekommen und kann
mich auch im AVR Studio nicht daran erinnern.
W.S. schrieb:> Ist mir völlig unverständlich. Ich pack das in die Schublade> "Fanatismus".
Dahin packe ich dich. Dann sind wir jetzt beide mehr oder weniger
glücklich.
M. K. schrieb:> There is no reason to ignore warnings.>> Und IMO hat er Recht, daher kommt beim Compiler auch immer die -Wall und> das liebe -Werror zum Einsatz
Klar ganz besonder bei
-Wunused-label
weil das auf vergessenes goto hinweist ;-)
-Wno-unused-result
Grad im embedded bereich gibt es Fälle wo das Ergebnis eben nicht
interessiert sondern allein die Bitschubserei mittendrin
Auch bei generierten Code wird man um schmerzfreie warnings nicht
drumherum kommen.
Dussel schrieb:> Was ist denn dann der Unterschied zwischen einem Fehler und einer> Warnung, wenn man eine Warnung wie einen Fehler behandeln soll?
Dass man sich darum kümmert die Warnung zu beseitigen.
In meiner jetzt fast 20-jährigen Berufserfahrung kann ich sagen: Es gibt
immer einen Weg einen Code so zu schreiben, dass der Compiler keine
Warnung wirft und das Programm dennoch so funktioniert wie man es sich
wünscht/vorstellt. ;)
Warnungen "ignoriere" ich bestenfalls für einen Testlauf, mehr aber auch
nicht. (z.B. wenn mich der Compiler informiert dass er bei der
LCD-Routine den "qualifier" "volatile" der globalen Variablen xyz
"entfernt" hat.)
M. K. schrieb:> Bei dir laufen Programme obwohl der Compiler Fehler geworfen hat?> Beeindruckend, meiner macht da erst gar kein Hexfile draus. ;)
Meinst du mich?
Du hast ausgedrückt, dass man Fehler nicht beseitigt, denn das sei der
Unterschied zu Warnungen, die man beseitigen soll.
Anscheinend sind manche hier schon betrunken. Ich noch nicht, ich mache
mich jetzt erst fertig. Bis morgen (Mittag) ;-)
(Das ist nicht ganz ernst gemeint, trotzdem verstehe ich nicht, was du
meinst. Weg bin ich aber wirklich.)
Rolf M. schrieb:>> Dennoch war es Yalu gelungen, letztlich ein C-Programm zu zimmern,>> dass dieses unterbieten konnte.>> Und mit diesem einen Beispiel hat er nachgewiesen, dass das "in der> Regel" so ist?
Nun, er hat es für den Fall nachgewiesen, für den es wirklich
niemand erwartet hätte, dass da noch was rauszuholen ist: für ein
extrem minimalistisches, in seiner Funktion recht überschaubares
(und dadurch auf Assemblerniveau gut zusammenzustauchendes) Stück
Code.
Für jeglichen Code von einigen Kilobyte Größe hätte (außer Moby)
ohnehin niemand gezweifelt, dass der Compiler das schafft, weil man
das auf Assemblerebene als Programmierer nicht mehr hinreiched gut
überblicken kann.
Dussel schrieb:> Du hast ausgedrückt, dass man Fehler nicht beseitigt, denn das sei der> Unterschied zu Warnungen, die man beseitigen soll.
Was? Wo hab ich denn das ausgedrückt?
Dussel schrieb:> Anscheinend sind manche hier schon betrunken. Ich noch nicht
Ich glaube du irrst dich hierbei...
Dussel schrieb:> (Das ist nicht ganz ernst gemeint, trotzdem verstehe ich nicht, was du> meinst. Weg bin ich aber wirklich.)
Ich meinte damit, dass man, neben den Fehlern zu beseitigen, auch die
Warnungen beseitigen sollte. Das war aber jetzt aus dem Kontext nicht
wirklich schwer zu verstehen. Hoffe du hast noch eine/n schöne/n
Abend/Nacht
Rolf M. schrieb:> Gibt es einen speziellen Grund, warum du das X mal postest, statt es> einfach zu tun?
Das Zitat war notwendig für den Kontext meiner Antwort. Es war nicht
weiter kürzbar. Wenn die Forensoftware dann sinnloserweise mehr Text
sehen will soll sie ihn meinetwegen bekommen, ist nicht mein Storage und
auch nicht meine Bandbreite, das hat der bestellt der sich diesen Unsinn
ausgedacht hat.
Bernd K. schrieb:> Erstens ist mir noch kein Compiler begegnet der mich wegen meiner int> main(void) angepfiffen hat
Du hast den Post von W.S. nicht richtig gelesen. W.S. hatte davon
gesprochen die main-Funktion als void zu deklarieren, was bei einigen
Compilern eben nicht funktioniert. Bei µC brauche ich für die
main-Funktion keinen Rückgabewert, da dieser niemals ausgewertet wird.
Das Dein
1
intmain(void)
läuft hat er ja gar nicht bestritten.
Seine Goto - Lösung finde ich an dieser Stelle gar nicht so schlecht.
Das bei C an dieser Stelle benutzte
1
while(1)
bringt an dieser Stelle auch nicht mehr Vorteile oder Übersicht.
Gerade als Anfänger muß man erst mal darauf kommen, daß man while so
aufrufen kann. Goto entspricht da eher der menschlichen Logik.
Das while(1) ist nach meinem Verständis ein genauso unsägliches
Konstrukt wie for(;;;). Es gibt gute Gründe warum andere
Programmiersprachen so was verbieten.
Es ist schon erstaunlich wie man sich an einem simplen goto aufgeilen
kann.
Ich bin der Meinung das man den Sprachumfang einer Programmiersprache
auch vollumfänglich benutzen kann, auch wenn es sich dabei um das
umstrittene goto oder bei C um while(1) bzw. for(;;;) handelt. Es gibt
immer Fälle wo solche Konstrukte durchaus Sinn machen und
übersichtlichen Code produzieren.
Sicherlich lassen sich auch immer andere Lösungen finden, aber ob die
nun wirklich besser sind steht auf einem anderen Blatt.
Zeno
Zeno schrieb:> Goto entspricht da eher der menschlichen Logik.
Genau. Das sieht man immer wieder an den Erstlingsprogrammmen von
Programmieranfängern. Menschliche Logik ist dafür der falsche Ansatz.
Wer sich an einem while(1) stört, hat noch nicht mal die Grundlagen der
Programmiersprache verinnerlicht. An der Stelle ist ein goto zwar
möglich, aber genauso wenig hilfreich, wie in all den anderen Beispielen
hier.
Sinnvoll ist es in sehr speziellen Fällen zur Fehlerbehandlung, aber
selbst da bietet C verkappte gotos in Form von setjmp/longjmp, und in
C++ wirft man dann Exceptions. Auf ganz kleinen Mikros wird's damit
allerdings eng. Da hilft dann goto.
Oliver
Oliver S. schrieb:> Und dann mal K&R lesen.
Okay:
The syntax of a for loop in C programming language is −
for ( init; condition; increment )
Und du schreibst:
for ( init; condition; increment; _???_ )
Fällt dir vielleicht jetzt was auf?
Zeno schrieb:> Das Deinint main(void) läuft hat er ja gar nicht bestritten.
Doch, er hat behauptet es gäbe irgendwelche Warnungen und mit goto könne
er sie abstellen. Das entspricht aber nicht der Wahrheit.
> Seine Goto - Lösung finde ich an dieser Stelle gar nicht so schlecht.
Wozu? Jeder Mensch benutzt an dieser Stelle ein while(1) Konstrukt.
Sollte ich jemals Software vererbt bekommen die an der Stelle ein goto
verwendet würde ich wahrscheinlich erstmal 26 Sekunden lang WTF???
WTF??? fragen und irgendeinen hinterhältigen versteckten schmutzigen
Trick vermuten den ich übersehen habe und nach weiteren 18 Sekunden in
denen ich so einen Trick nicht finden kann den ganzen Schwachsinn gegen
ein ganz normales while(1) austauschen.
An irgendwelchen von W.S. herbeiphantasierten (aber nicht existierenden)
Warnungen ändert das nicht das geringste. Und mit dem Rückgabewert hat
das auch nichts zu tun.
Dann schreibt doch einfach:
#define forever for(;;)
und dann im Programm einfach:
forever
{
}
so sollte auch der letzte DAP das lesen koennen.
DAP = duemmster anzunehmender Programmierer
W.S. schrieb:> Dussel schrieb:>> Das 'Schlimmste', das ich in dem Fall erlebt habe, war eine>> Warnung 'Unreachable Statement'.>> Reicht das nicht?>> Entweder gibt es vom Compiler keine Fehler und Warnungen oder es liegt> eben was im Argen - was auch immer.
Nein. Eine Warnung heißt nicht automatisch, dass der Code falsch ist,
und die Abwesenheit einer Warnung heißt genausowenig, dass der Code
perfekt ist. Das erkennt man schon alleine daran, dass unterschiedliche
Compiler auch in unterschiedlichen Situationen warnen.
> Hier hab ich es also offensichtlich mit Leuten zu tun, die aus schierer> Abneigung gegen ein simples goto selbst Compilerwarnungen in Kauf> nehmen.
Was für ein Unsinn. Wenn ich bei deinem Beispiel das "return 0;"
hinschreibe, kommt bei mir irgendwie keine Warnung, trotz Nichtbenutzung
von goto. Die Warnung kommt doch auch gar nicht, weil du kein goto
benutzt hast, sondern weil du das return unterschlagen hast. Also ist
deren Vermeidung auch überhaupt kein Argument für goto.
> Ist mir völlig unverständlich.
Das merkt man...
M. K. schrieb:> In meiner jetzt fast 20-jährigen Berufserfahrung kann ich sagen: Es gibt> immer einen Weg einen Code so zu schreiben, dass der Compiler keine> Warnung wirft und das Programm dennoch so funktioniert wie man es sich> wünscht/vorstellt. ;)
Einen Weg gibt es immer. Die Frage ist nur, ob man es immer hinnimmt, im
Code Verrenkungen anstellen zu müssen, nur weil der Compiler bei einem
eigentlich völlig korrekten Code-Konstrukt warnt.
M. K. schrieb:> Dussel schrieb:>> Du hast ausgedrückt, dass man Fehler nicht beseitigt, denn das sei der>> Unterschied zu Warnungen, die man beseitigen soll.>> Was? Wo hab ich denn das ausgedrückt?
Hier:
M. K. schrieb:> Dussel schrieb:>> Was ist denn dann der Unterschied zwischen einem Fehler und einer>> Warnung, wenn man eine Warnung wie einen Fehler behandeln soll?>> Dass man sich darum kümmert die Warnung zu beseitigen.Zeno schrieb:> Du hast den Post von W.S. nicht richtig gelesen. W.S. hatte davon> gesprochen die main-Funktion als void zu deklarieren, was bei einigen> Compilern eben nicht funktioniert. Bei µC brauche ich für die> main-Funktion keinen Rückgabewert, da dieser niemals ausgewertet wird.
Ich verstehe allerdings nicht, wozu das gut sein soll. Ich hatte noch
nie ein Problem dadurch, dass ich main() einen int zurückliefern hab
lassen. Im schlimmsten Fall braucht das das eine oder andere zusätzliche
Byte, aber wenn der Speicher schon so knapp ist, dass das ein Problem
ist, hab ich eh verloren.
> Seine Goto - Lösung finde ich an dieser Stelle gar nicht so schlecht.
Ich finde es widersinnig. Nur um sich in main() das return zu sparen,
nutzt er goto, weil sein Compiler in dem Fall nicht warnt - zumindest in
der Version, die er aktuell nutzt. Das ist dann in seinen Augen das
Argument dafür, für Endlosschleifen grundsätzlich immer goto zu
verwenden.
> Das bei C an dieser Stelle benutzte while(1) bringt an dieser Stelle auch> nicht mehr Vorteile oder Übersicht.
Doch, finde ich schon. Es ist konsistent. Ich habe eine Schleife, also
schreib ich die auch als eine solche hin, auch dann, wenn sie mal kein
Abbruchkriterium hat. Wobei ich for (;;) bevorzuge, da ich da die
Bedinung dann auch wirklich weglassen kann, während ich beim while in
dem Fall eine Pseudo-Bedingung hinschreiben muss. Man könnte aber
natürlich schreiben:
1
#define WEIHNACHTEN 1
2
#define OSTERN 2
3
4
while(WEIHNACHTEN!=OSTERN)
;-)
> Das while(1) ist nach meinem Verständis ein genauso unsägliches> Konstrukt wie for(;;;). Es gibt gute Gründe warum andere> Programmiersprachen so was verbieten.
Mir würde keiner einfallen, und "unsäglich" finde ich den auch nicht,
sondern im Gegenteil viel eher "natürlich", als für Endlosschleifen auf
einmal einen ganz anderen Konstrukt zu verwenden, als bei allen anderen
Schleifen.
> Ich bin der Meinung das man den Sprachumfang einer Programmiersprache> auch vollumfänglich benutzen kann,
Ja, sehe ich auch so, wobei man aber nicht unbedingt alles benutzen
muss, nur weil es eben da ist. Man benutzt immer das, was einem an der
Stelle am sinnvollsten erscheint. Das kann auch dazu führen, dass man
bestimmte Teile der Sprache nicht nutzt. Es gibt keine Notwendigkeit,
zwingend jedes Element der Sprache auch nutzen zu müssen.
> Sicherlich lassen sich auch immer andere Lösungen finden, aber ob die> nun wirklich besser sind steht auf einem anderen Blatt.
Richtig.
Rolf M. schrieb:> Was für ein Unsinn. Wenn ich bei deinem Beispiel das "return 0;"> hinschreibe, kommt bei mir irgendwie keine Warnung, trotz Nichtbenutzung> von goto. Die Warnung kommt doch auch gar nicht, weil du kein goto> benutzt hast, sondern weil du das return unterschlagen hast.
Die Warnung verschwindet auch dann wenn man das return NICHT
hinschreibt aber ein while(1) hat das niemals verlassen wird.
Es ist diesbezüglich Jacke wie Hose ob man das mit while oder goto
macht, in beiden Fällen gibts keine Warnung weil in beiden Fällen jeder
Compiler der sein Geld wert ist erkennt daß die Funktion niemals
zurückkehrt und die Warnung verschwindet sobald das endlose while dort
steht.
Probierts doch selber mal aus.
Bernd K. schrieb:> Probierts doch selber mal aus.
Ok, hab ich mal getan. Bei mir (gcc 5.2.1) kommt weder bei der while-,
noch bei der goto-Variante eine Warnung, egal ob ich das return
hinschreibe oder nicht. Getestet mit -pedantic -Wall -Wextra, einmal im
C89- und einmal im C99-Modus. Mit anderen Worten: Die Rechtfertigung von
W.S., an dieser Stelle goto zu benutzen, um die Warnung zu vermeiden,
ist völliger Blödsinn.
Ohne die Endlosschleife kommt übrigens bei fehlendem return nur im
C89-Modus eine Warnung.
Rolf M. schrieb:> Ohne die Endlosschleife kommt übrigens bei fehlendem return nur im> C89-Modus eine Warnung.
Zumindest in C++ ist das return statement in der main() Funktion
optional und da wird auch kein vernünftiger Compiler eine Warnung
ausgeben. Vielleicht gibt es diese Erweiterung auch in aktuelleren C
Standards?
Rolf M. schrieb:> Einen Weg gibt es immer. Die Frage ist nur, ob man es immer hinnimmt, im> Code Verrenkungen anstellen zu müssen, nur weil der Compiler bei einem> eigentlich völlig korrekten Code-Konstrukt warnt.
Wenn das Konstrukt korrekt wäre würde der Compiler nicht warnen.
Rolf M. schrieb:> Hier:
Da schrieb ich nur, dass man die Warnungen beseitigen solle, ich schrieb
da aber nicht, dass man nur die Warnungen beseitigen solle noch dass man
die Fehler nicht beseitigen solle. Keine Ahnung wie ihr auf sowas
geschlossen habt.
M. K. schrieb:> Wenn das Konstrukt korrekt wäre würde der Compiler nicht warnen.
Umgekehrt. Wenn das Konstrukt nicht korrekt wäre, würde der Compiler
nicht nur warnen.
Manche Compiler warnen bei unbenutzten Variablen. Trotzdem ist ein
Programm, das eine nicht benutzte Variable enthält, vollkommen korrekt
und unterscheidet sich bei heutigen Compilern im Ergebnis nicht von
einem Programm, das diese Variable nicht enthält.
M. K. schrieb:> Da schrieb ich nur, dass man die Warnungen beseitigen solle, ich schrieb> da aber nicht, dass man nur die Warnungen beseitigen solle noch dass man> die Fehler nicht beseitigen solle. Keine Ahnung wie ihr auf sowas> geschlossen habt.
Doch, genau das. Deiner Aussage nach ist der Unterschied zwischen
Fehlern und Warnungen, dass man Warnungen beseitigen soll. Fehler solle
man in dem Aspekt anders [unterschiedlich zu Warnungen] behandeln, was
ich so interpretiere, dass man Fehler eben nicht beseitigen soll.
Genau genommen hätte ich den zweiten Teil nicht schreiben sollen. Die
Diskussion führt zu nichts.
Worin wir uns wohl alle (zumindest insgeheim) einig sind ist, dass
Anfänger Goto nicht verwenden sollen.
Wenn man weiß, was man macht, gibt es Anwendungsfälle, in denen Goto
sinnvoll ist (wie schon seit einem Monat immer wieder gesagt wird).
Welche Fälle das sind, muss man im Zweifelsfall mit seinen Vorgesetzten
und Mitarbeitern diskutieren.
M. K. schrieb:> Rolf M. schrieb:>> Einen Weg gibt es immer. Die Frage ist nur, ob man es immer hinnimmt, im>> Code Verrenkungen anstellen zu müssen, nur weil der Compiler bei einem>> eigentlich völlig korrekten Code-Konstrukt warnt.>> Wenn das Konstrukt korrekt wäre würde der Compiler nicht warnen.
Wie ich schon schrieb: Eine Warnung heißt nicht zwangsläufig, dass es
falsch ist. Es heißt nur, dass der Compiler etwas gefunden hat, das
dessen Hersteller für verdächtig hält.
> Rolf M. schrieb:>> Hier:>> Da schrieb ich nur, dass man die Warnungen beseitigen solle, ich schrieb> da aber nicht, dass man nur die Warnungen beseitigen solle noch dass man> die Fehler nicht beseitigen solle. Keine Ahnung wie ihr auf sowas> geschlossen habt.
Du hast auf die Frage, was der Unterschied zwischen Warnung und Fehler
ist, geantwortet, dass man Warnungen beseitigen muss. Wenn das der
Unterschied zu Fehlern ist, heißt das aber, dass man Fehler nicht
beseitigen muss.
asdf schrieb:> Zeno schrieb:>> ein genauso unsägliches>> Konstrukt wie for(;;;)>> Vor allem deshalb, weil es das gar nicht gibt :-)
Na da ist aber einer froh, daß er was gefunden hat. Ja da ist ein ; zu
viel. Das ändert aber dennoch nichts daran, das die for-Schleife ohne
Parameter ein unsägliches Konstrukt ist, was sich einem nicht logisch
erschließt. Deshalb muß man's halt nachlesen.
Ich komme nicht aus der C-Ecke und benutze derzeit C nur um ab und zu
einen µC zu programmieren. Bisher bin ich ohne for(;;) ausgekommen.
Meine Endlosschleife habe ich bisher mit while(1) gemacht und werde dies
auch weiterhin so tun oder W.S. Ansatz mit dem goto verwenden.
ZEno
Zeno schrieb:> Bisher bin ich ohne for(;;) ausgekommen.> Meine Endlosschleife habe ich bisher mit while(1) gemacht
Eine for-Schleife ohne Parameter findest du also "unsäglich", aber eine
while-Schleife ohne Parameter ist in Ordnung für dich?
Na gut, jedem Tierchen sein Pläsierchen :-)
Bernd K. schrieb:> Zeno schrieb:>> Das Deinint main(void) läuft hat er ja gar nicht bestritten.>> Doch, er hat behauptet es gäbe irgendwelche Warnungen und mit goto könne> er sie abstellen. Das entspricht aber nicht der Wahrheit.
Nein Du hast den Post von W.S. nicht richtig gelesen. Er hat folgendes
geschrieben:
W.S. schrieb:> daß main vom Typ int ....
Die Compilermecker bezieht er auf den (zu definierenden) Rückgabewert
von main, also auf das int vor main.
CCS von TI meckert bei eingestellten GCC wenn man main so definiert:
1
voidmain(void)
2
{
3
....
4
}
Dabei ist es egal ob man als Endlosschleife while(1), for(;;) oder
W.S.'s goto nimmt.
Zeno
Rolf M. schrieb:> Es gibt keine Notwendigkeit,> zwingend jedes Element der Sprache auch nutzen zu müssen
Das habe ich so (Betonung auf zwingend) nicht gesagt. Ich wollte meinen
Post so verstanden wissen, daß man den kompletten Sprachumfang nutzen
kann wenn man dies denn in bestimmten Situationen für vorteilhaft
erachtet.
Zeno
Hugo schrieb:> while-Schleife ohne Parameter ist in Ordnung für dich?
1 ist bei while(1) wohl kein Parameter? Ohne Parameter müßte es ja so
heißen while().
Ich habe nicht gesagt, das ich das while(1) gut finde, aber wenn man
zwischen mehreren Seuchen wählen muß, um zum Ziel zu kommen, dann muß
man sich halt für Eine entscheiden.
Zeno
Zeno schrieb:> Ohne Parameter müßte es ja so> heißen while().
Warte, warte noch ein While-chen,
dann kommt Goto auch zu Dir!
Mit dem dem kleinen For-Next Schleifchen
steht es dann vor Deiner Tür.
MfG Paul
Zeno schrieb:> W.S. schrieb:>> daß main vom Typ int ....>> Die Compilermecker bezieht er auf den (zu definierenden) Rückgabewert> von main, also auf das int vor main.
Na und? Er hat aber geschrieben daß er es [wasauchimmer] mit goto
abstellen kann, mit while(1) aber nicht. Das ist aber Unfug denn auch
mit while(1) gibt es keine Warnung, mithin also keinen Grund für goto an
der Stelle.
1
intmain(void){
2
while(1){
3
// tuwas
4
}
5
}
gibt keine Warnung. Und zwar weil alles korrekt ist. Genauso wie man es
erwarten würde. Also was soll der ganze Aufriss und welche Rolle soll
goto hier spielen die das while(1) nicht erfüllen kann?
Dussel schrieb:> Doch, genau das. Deiner Aussage nach ist der Unterschied zwischen> Fehlern und Warnungen, dass man Warnungen beseitigen soll. Fehler solle> man in dem Aspekt anders [unterschiedlich zu Warnungen] behandeln, was> ich so interpretiere, dass man Fehler eben nicht beseitigen soll.
Sorry, aber so einen Unsinn hab ich schon lange nicht mehr gelesen. Nur
weil ich nicht schrieb, dass man auch Fehler beseitigen soll (genauer:
ich hab gar nichts zu Fehlern geschrieben) soll ich ausgesagt haben,
Fehler müsse man nicht beseitigen? Ich hab auch nichts zu, z.B.,
while-Schleifen geschrieben. Heißt das jetzt, dass ich sie generell für
unnötig erachte?
Dussel schrieb:> Manche Compiler warnen bei unbenutzten Variablen. Trotzdem ist ein> Programm, das eine nicht benutzte Variable enthält, vollkommen korrekt> und unterscheidet sich bei heutigen Compilern im Ergebnis nicht von> einem Programm, das diese Variable nicht enthält.
Und ob es sich unterscheidet: Eine unbenutze Variable verschwendet
Resourcen, der Compiler warnt zurecht davor. Und welchen Grund gäbe es,
eine unbenutzte Variable im Code zu lassen? Welchen Vorteil hat man denn
davon?
M. K. schrieb:> Eine unbenutze Variable verschwendet> Resourcen,
Wenn der Compiler was taugt, merkt er, daß die Variable nicht benutzt
ist und wird keine Recourcen dafür verschwenden!
Thomas E. schrieb:> M. K. schrieb:>> Eine unbenutze Variable verschwendet>> Resourcen,>> Wenn der Compiler was taugt, merkt er, daß die Variable nicht benutzt> ist und wird keine Recourcen dafür verschwenden!
Und wenn es der Compiler nicht merkt, wird er auch keine Warnung dazu
ausgeben.
Die Warnung dient also einzig und allein dazu, dem Programmierer
folgendes mitzuteilen:
1
Hey, es gibt doch sicher einen Grund, warum du hier die Variable xy
2
definiert hast. Kann es sein, dass da noch ein Stück Programmcode
3
fehlt, der diese Variable verwendet. Wenn ja, dann solltest du das
4
Programm noch nicht verkaufen, sondern erst einmal zu Ende schreiben."
Thomas E. schrieb:> M. K. schrieb:>> Eine unbenutze Variable verschwendet>> Resourcen,>> Wenn der Compiler was taugt, merkt er, daß die Variable nicht benutzt> ist und wird keine Recourcen dafür verschwenden!
Oder er gibt statt einer Warnung einen Hinweis aus.
M. K. schrieb:> Sorry, aber so einen Unsinn hab ich schon lange nicht mehr gelesen. Nur> weil ich nicht schrieb, dass man auch Fehler beseitigen soll (genauer:> ich hab gar nichts zu Fehlern geschrieben) soll ich ausgesagt haben,> Fehler müsse man nicht beseitigen?
Nein. Weil du gesagt hast, dass das der UNTERSCHIED zwischen Warnung
und Fehler ist. Was ist daran denn so schwer zu begreifen?
> Ich hab auch nichts zu, z.B., while-Schleifen geschrieben. Heißt das> jetzt, dass ich sie generell für unnötig erachte?
Wenn du gesagt hättest, dass der UNTERSCHIED zwischen while und goto
für eine Endlosschleife ist, dass du goto dort für sinnvoll erachtest,
dann hättest du das damit tastsächlich gesagt.
> Und ob es sich unterscheidet: Eine unbenutze Variable verschwendet> Resourcen, der Compiler warnt zurecht davor. Und welchen Grund gäbe es,> eine unbenutzte Variable im Code zu lassen? Welchen Vorteil hat man denn> davon?
Nehmen wir ein anderes Beispiel: Ein unbenutzter Parameter erzeugt in
gcc auch eine Warnung. Manchmal braucht man einen solchen aber, wenn die
API es erfordert, z.B. wenn man eine Callback-Funktion definiert, die
eben zwingend diesen Parameter haben muss. Oder wenn im Zuge der
Weiterentwicklung der Parameter nicht mehr nötig ist, die API sich aber
nicht ändern darf. Sowas passiert mir praktisch regelmäßig. Ein gängiger
Weg, die Warnung zu unterbinden, sieht dann etwa so aus:
1
voidsighandler(intsig)
2
{
3
sig=sig;
4
// ...
5
}
oder auch:
1
voidsighandler(intsig)
2
{
3
(void)sig;
4
// ...
5
}
Da warnt der Compiler dann nicht mehr. Was in meinen Augen irgendwie
schon weh tut. Man muss einen völlig sinnlosen Quatsch hinschreiben, nur
um eine nutzlose Warnung wegzubekommen.
Alternativ kann man bei GCC mit __attribute__((unused)) auch eine
Compiler-Erweiterung nutzen, um die Warnung loszuwerden.
Yalu X. schrieb:> Die Warnung dient also einzig und allein dazu, dem Programmierer> folgendes mitzuteilen:>> Hey, es gibt doch sicher einen Grund, warum du hier die Variable xy> definiert hast. Kann es sein, dass da noch ein Stück Programmcode> fehlt, der diese Variable verwendet. Wenn ja, dann solltest du das> Programm noch nicht verkaufen, sondern erst einmal zu Ende schreiben."
Ja, mit anderen Worten: Der Compiler glaubt zu wissen, warum du das so
gemacht hast und dass das so falsch ist. Wenn du aber einen guten Grund
hast, musst du dir irgendeinen work-around für die falsche Warnung
einfallen lassen.
nichtCler schrieb:>> Wenn der Compiler was taugt, merkt er, daß die Variable nicht benutzt>> ist und wird keine Recourcen dafür verschwenden!>> Oder er gibt statt einer Warnung einen Hinweis aus.
Was ist denn nun wieder der Unterschied zwischen einer Warnung und einem
Hinweis? Und bei welchem Compiler gibt es sowas?
Rolf M. schrieb:> nichtCler schrieb:>>> Wenn der Compiler was taugt, merkt er, daß die Variable nicht benutzt>>> ist und wird keine Recourcen dafür verschwenden!>>>> Oder er gibt statt einer Warnung einen Hinweis aus.>> Was ist denn nun wieder der Unterschied zwischen einer Warnung und einem> Hinweis? Und bei welchem Compiler gibt es sowas?https://de.wikipedia.org/wiki/Warnunghttps://de.wikipedia.org/wiki/Hinweis
Ich kenne keinen Compiler der soviel taugt, daß er da einen Unterschied
macht.
W.S. schrieb:> Bei diesem Konstrukt merkt der Compiler endlich (!), daß es nie und> nimmer zurückgeht und hält die Fresse.
Er wird nur meckern, weil auch eine while(1) unterbrochen werden kann
(mit break). Und in diesem Falle würde er dann auch zum Ende der Main
gelangen. Wenn er aber erkennen soll, dass innerhalb der while(1)
nirgends ein break; zu finden ist, dies aber nicht tut, darf man sich
nicht über die Sprache und die Verwendung dessen Elemente beschweren,
sondern über den Compiler.
Ob nun eine while(1) oder ein goto optisch und styleguide-mäßig sauberer
ist, ist die eine (nicht beantwortbare) Frage. Die andere ist eine
Funktion mit Rückgabewert kein return schenken zu wollen. Auch wenn es
nie erreicht wird (genauer: erreicht werden soll), gehört es aus meiner
Sicht immer dahin. Daher mache ich mir diese "Mühe" und schreibe ein
return 0; hin, zusammen mit dem Kommentar, dass das return nie erreicht
werden kann/soll und dass der Compiler ein void main() nicht akzeptiert.
Sonst guckt nachher jemand anderes mal rein und sucht sich ein Wolf, wo
denn ein Wert zurückgegeben wird. Besonders wenn dieser nicht weiß, dass
die main ein int-Rückgabewert haben MUSS.
Dussel schrieb:> Das 'Schlimmste', das ich in dem Fall erlebt habe, war eine> Warnung 'Unreachable Statement'. Wenn du so dünnhäutig bist, dass dich> eine Warnung so fertig macht, kannst du auch Goto verwenden, aber das> ist absolut nicht die Regel.
Bei Nutzung von Goto muss in diesem Fall aber ebenfalls die Warnung
kommen, da der Befehl ebenfalls nie ausgeführt wird. Sollte dies aber
nicht so sein, wäre das für mich ein Grund (zumindest bei diesem
Compiler) niewieder ein goto zu verwenden. Wer weiß, welche Warnungen
oder sogar Fehler er sonst noch übersieht. Außerdem wäre wohl ein
anderer Compiler angebracht.
Michael S. schrieb:> Daher mache ich mir diese "Mühe" und schreibe ein> return 0; hin, zusammen mit dem Kommentar, dass das return nie erreicht> werden kann/soll
Code hinschreiben der nicht erreicht werden kann, ist einfach nur
mistiger Stil.
Es scheint einigen hier nicht klar zu sein, dass main() eben keine
Return-Anweisung benötigt, aber sehr wohl mit dem Rückgabe-Typ "int"
definiert werden muss.
Siehe C-Standard (ISO/IEC 9899:2011):
1
5.1.2.2.3 Program termination
2
3
If the return type of the main function is a type compatible
4
with int, a return from the initial call to the main function
5
is equivalent to calling the exit function with the value
6
returned by the main function as its argument; reaching
7
the } that terminates the main function returns a value of 0.
Um es nochmals klar auszusprechen: Ein fehlendes "return" in "int
main(...)" ist absolut identisch zu "return 0" bzw. zu "exit(0)"!
Einfach mal den Standard lesen und sich dran halten.
Nächstes Thema: Eine Funktion mit einem Rückgabe-Typ ungleich "void" und
einer Endlosschleife ohne "break" und "continue" benötigt natürlich auch
kein "return X" weil dieser Code selbstverständlich nie erreicht werden
kann. Gute Compiler warnen genau vor dem nicht-erreichbaren Code!
Michael S. schrieb:> Wenn er aber erkennen soll, dass innerhalb der while(1)> nirgends ein break; zu finden ist, dies aber nicht tut, darf man sich> nicht über die Sprache und die Verwendung dessen Elemente beschweren,> sondern über den Compiler.
Genau das ist das klassische C-Problem. Jeder (Compilerhersteller) meint
er müsse den Compiler neu erfinden und macht bei den Basics etwas
anders. Der eine Compiler meckert wenn man main als void deklariert der
andere (z.B. Xcode) gibt nur eine Warning aus. Der nächste verlangt
zwingend das int vor main und ein return.. und so weiter und so weiter.
Oder man schaue sich mal die Deklaration der Interruptroutinen an - das
macht jeder Compilerhersteller anders.
Zeno
Programmierer schrieb:> Siehe C-Standard (ISO/IEC 9899:2011):> Um es nochmals klar auszusprechen: Ein fehlendes "return" in "int> main(...)" ist absolut identisch zu "return 0" bzw. zu "exit(0)"!>> Einfach mal den Standard lesen und sich dran halten.
Ja, aber das ist wie gesagt nicht schon immer drin, sondern "erst" seit
C99. Leider stecken viele Compiler (und Programmierer) noch im Jahr 1989
fest, wo das noch nicht so war. Und es gilt auch nur für die Funktion
main().
Mani W. schrieb:> Vielleicht wäre statt "Goto" besser "Go Away" angebracht...
Es gibt ja auch noch den eigentlich viel cooleren umgekehrten Konstrukt
names COMEFROM. Zwar nicht in C, aber in ein paar anderen Sprachen. Man
schreibt also das Label an die Stelle, wo man springen will und am
Sprungziel ein comefrom label.
Damit würde die Endlosschleife so aussehen:
comefrom label
// schleifeninhalt
label:
Zeno schrieb:> Genau das ist das klassische C-Problem. Jeder (Compilerhersteller) meint> er müsse den Compiler neu erfinden und macht bei den Basics etwas> anders. Der eine Compiler meckert wenn man main als void deklariert der> andere (z.B. Xcode) gibt nur eine Warning aus. Der nächste verlangt> zwingend das int vor main und ein return.. und so weiter und so weiter.
Deshalb gibt es eine ISO-Norm. Die sagt ganz klar, dass int immer
funktionieren muss. Wer dann trotzdem stattdessen void benutzt, begibt
sich eben in den Bereich der Compilerspezifika.
Natürlich ist es bei µCs so, dass main() normalerweise nie zurückkehrt
und man das int nicht unbedingt bräuchte, aber µCs sind in der Hinsicht
eben ein Spezialfall. int als Returntyp funktioniert dort aber auch.
Rolf M. schrieb:> oder auch:void sighandler(int sig)> {> (void)sig;> // ...> }> Man muss einen völlig sinnlosen Quatsch hinschreiben, nur> um eine nutzlose Warnung wegzubekommen.
Ob eine Meldung nutzlos ist oder nicht hängt wohl vom Betrachter ab.
Rolf M. schrieb:> Es gibt ja auch noch den eigentlich viel cooleren umgekehrten Konstrukt> names COMEFROM.
Auch unter dem Namen catch oder except bekannt.
Mikro 7. schrieb:> Ob eine Meldung nutzlos ist oder nicht hängt wohl vom Betrachter ab.> sighandler(int)> {> // ...> }
...quittiert gcc mit:
"error: parameter name omitted"
da es in C nicht gestattet ist, namenlose Parameter zu haben.
Rolf M. schrieb:> Nein. Weil du gesagt hast, dass das der UNTERSCHIED zwischen Warnung> und Fehler ist. Was ist daran denn so schwer zu begreifen?
Dass ich das nie geschrieben habe. Was ich nicht begreife ist wie
Personen wie du auf so etwas kommen? Ich mein, hey. Ich wüsste jetzt
nicht mal wie ich überhaupt einen Compiler dazu bekomme einen
fehlerhaften Code zu übersetzen, so tief geht mein Wissen bzgl. des
GCC-Compilers nicht. Die Aussage "Fehler soll man beseitigen." ist daher
nach meinem Wissen auch unsinn denn "Fehler muss man beseitigen" da
sonst erst gar kein Programm erzeugt wird.
Rolf M. schrieb:> Nehmen wir ein anderes Beispiel: Ein unbenutzter Parameter erzeugt in> gcc auch eine Warnung. Manchmal braucht man einen solchen aber, wenn die> API es erfordert, z.B. wenn man eine Callback-Funktion definiert, die> eben zwingend diesen Parameter haben muss. Oder wenn im Zuge der> Weiterentwicklung der Parameter nicht mehr nötig ist, die API sich aber> nicht ändern darf. Sowas passiert mir praktisch regelmäßig.
Warum darf sich denn die API nicht ändern? Den Grund dafür würde ich
gerne mal wissen. Dass ein Compiler vor einem unbenutzten Parameter
warnt ist doch völlig richtig und OK. Ist der Parameter unnötig dann
gehört er da auch nicht hin. Und dein Beispiel hat noch einen Haken:
Wenn sich die API nicht ändern darf und man einen Parameter nicht mehr
braucht muss er ja vorher gebraucht worden sein, er dürfte gar nicht
unbenutzt rumliegen. Wenn er jetzt aber doch unbenutzt rumliegt hat man
die API ja doch verändert. Das klingt nach klassischem Eigentor.
Rolf M. schrieb:> Ein gängiger> Weg, die Warnung zu unterbinden, sieht dann etwa so aus:
Was völlig wurscht ist da der Compiler das Programm auch mit Warnung
übersetzt. Den gezeigten Spass könntest du dir auch sparen. Statt zu
überlegen, wie die Warnung nicht mehr angezeigt wird wäre man besser
beraten zu überlegen wie die Warnung erst gar nicht mehr auftritt.
Rolf M. schrieb:> Ja, mit anderen Worten: Der Compiler glaubt zu wissen, warum du das so> gemacht hast und dass das so falsch ist. Wenn du aber einen guten Grund> hast, musst du dir irgendeinen work-around für die falsche Warnung> einfallen lassen.
Der Compiler sieht nur, dass das, was man da gemacht hat, keinen
Sinn/Nutzen ergibt und er sagt hier nur "Denk nochmal drüber nach was du
da gemacht hast.". Es gibt keine falschen Warnungen und es gibt daher
auch keinen Grund Warnungen zu ignorieren. Warnungen ignoriert man aus
Bequemlichkeit. Und ja, ich hab auch schon Warnungen aus Bequemlichkeit
ignoriert.
M. K. schrieb:> Dass ein Compiler vor einem unbenutzten Parameter> warnt ist doch völlig richtig und OK.
Das ist richtig.
M. K. schrieb:> Ist der Parameter unnötig dann> gehört er da auch nicht hin.
Das ist falsch.
M. K. schrieb:> Rolf M. schrieb:>> Nein. Weil du gesagt hast, dass das der UNTERSCHIED zwischen Warnung>> und Fehler ist. Was ist daran denn so schwer zu begreifen?>> Dass ich das nie geschrieben habe. Was ich nicht begreife ist wie> Personen wie du auf so etwas kommen?
Ich hab's doch schon mal zitiert. Es steht da schwarz auf weiß. Wie
kannst du das denn leugnen? Aber gerne nochmal:
M. K. schrieb:> Dussel schrieb:>> Was ist denn dann der Unterschied zwischen einem Fehler und einer>> Warnung, wenn man eine Warnung wie einen Fehler behandeln soll?>> Dass man sich darum kümmert die Warnung zu beseitigen.
Also Frage und Antwort in einem Satz zusammenefasst: "Der Unterschied
zwischen einem Fehler und einer Warnung ist, dass man sich darum kümmert
die Warnung zu beseitigen."
> Ich mein, hey. Ich wüsste jetzt nicht mal wie ich überhaupt einen> Compiler dazu bekomme einen fehlerhaften Code zu übersetzen, so tief geht> mein Wissen bzgl. des GCC-Compilers nicht.
Ich auch nicht. Deshalb wundern uns ja hier über deine Aussage, dass man
nur Warnungen beseitigt. Wenn du das nicht so gemeint hast, ist ja ok,
dann kannst du das ja einfach sagen. Wäre jedenfalls besser, als zu
behaupten, du hättest es nicht so hingeschrieben.
> Rolf M. schrieb:>> Nehmen wir ein anderes Beispiel: Ein unbenutzter Parameter erzeugt in>> gcc auch eine Warnung. Manchmal braucht man einen solchen aber, wenn die>> API es erfordert, z.B. wenn man eine Callback-Funktion definiert, die>> eben zwingend diesen Parameter haben muss. Oder wenn im Zuge der>> Weiterentwicklung der Parameter nicht mehr nötig ist, die API sich aber>> nicht ändern darf. Sowas passiert mir praktisch regelmäßig.>> Warum darf sich denn die API nicht ändern? Den Grund dafür würde ich> gerne mal wissen.
Weil noch andere Komponenten davon abhängig sind, und deren Ersteller
sich bedankt, wenn er die umprogrammieren muss wegen eines Parameters,
der eigentlich gar keine Rolle mehr spielt - nur damit ich keine Warnung
in meinem Code bekomme. Aber darum geht's doch gar nicht. Von mir aus
lass dieses Beispiel weg und belasse es bei der Callback-Funktion.
> Dass ein Compiler vor einem unbenutzten Parameter warnt ist doch völlig> richtig und OK.
Ein unbenutzter Parameter ist erstmal kein Fehler. Es ist eben wie ich
oben geschrieben hab: Der Hersteller des Compilers hält das für
verdächtig und warnt deshalb. Dass der Parameter nicht benutzt wird,
könnte ja darauf hinweisen, dass was fehlt.
> Ist der Parameter unnötig dann gehört er da auch nicht hin.
Tja, wenn äußere Zwänge ihn nötig machen, gehört er eben hin. Leider
kommt dann aber eine Warnung, wenn man ihn nicht auch benutzt.
> Und dein Beispiel hat noch einen Haken:> Wenn sich die API nicht ändern darf und man einen Parameter nicht mehr> braucht muss er ja vorher gebraucht worden sein, er dürfte gar nicht> unbenutzt rumliegen. Wenn er jetzt aber doch unbenutzt rumliegt hat man> die API ja doch verändert. Das klingt nach klassischem Eigentor.
Wie kommst du denn darauf? Wenn die Funktion den Parameter nicht mehr
benötigt, aber ansonsten ihre Arbeit einfach weiter ganz normal tut, was
soll sich dann an der API geändert haben?
> Rolf M. schrieb:>> Ein gängiger Weg, die Warnung zu unterbinden, sieht dann etwa so aus:>> Was völlig wurscht ist da der Compiler das Programm auch mit Warnung> übersetzt.
Hä? Jetzt machst du mich fertig. Du schreibst doch selbst, dass man
Warnungen beseitigt. Jetzt ist es auf einmal wurscht?
> Den gezeigten Spass könntest du dir auch sparen. Statt zu> überlegen, wie die Warnung nicht mehr angezeigt wird wäre man besser> beraten zu überlegen wie die Warnung erst gar nicht mehr auftritt.
Im Falle des Signalhandlers wie? Indem ich versuche, die ISO-C-Norm so
zu beeinflussen, dass der Signalhandler die Signalnummer nicht mehr
übergeben bekommt und dann ein Jahrzehnt warte, bis die Compiler das
auch umgesetzt haben? Oder was schlägst du vor zu tun, wenn ein Callback
einen Parameter nicht braucht?
> Rolf M. schrieb:>> Ja, mit anderen Worten: Der Compiler glaubt zu wissen, warum du das so>> gemacht hast und dass das so falsch ist. Wenn du aber einen guten Grund>> hast, musst du dir irgendeinen work-around für die falsche Warnung>> einfallen lassen.>> Der Compiler sieht nur, dass das, was man da gemacht hat, keinen> Sinn/Nutzen ergibt
Nein, das sieht er nicht, da Compiler keine künstliche Intelligenz
haben, die sowas erkennen könnte. Sie können nur nach einfachen Regeln
auf typische Stolperfallen prüfen und da pauschal warnen, ohne den
tatsächlichen Sinn oder Unsinn wirklich zu erkennen.
> und er sagt hier nur "Denk nochmal drüber nach was du da gemacht hast.".
Ok, hab ich getan und festgestellt: Ich hab hier das richtige gemacht.
Leider geht die Warnung davon nicht weg.
> Es gibt keine falschen Warnungen und es gibt daher auch keinen Grund> Warnungen zu ignorieren.
Natürlich gibt es falsche Warnungen. Die treten vor allem dann auf, wenn
der Compiler anfängt, an Stellen zu warnen, die eigentlich nicht falsch
sind sondern nur vielleicht falsch sein könnten.
Und ignorieren will ich die Warnung auch nicht, aber wenn sie an der
Stelle unberechtigt ist, da der Code dort genau so ist, wie er sein
muss, muss ich sie entweder ignorieren oder auf irgendeine Weise ruhig
stellen.
Rolf M. schrieb:> Ich hab's doch schon mal zitiert. Es steht da schwarz auf weiß. Wie> kannst du das denn leugnen? Aber gerne nochmal:>> M. K. schrieb:>> Dussel schrieb:>>> Was ist denn dann der Unterschied zwischen einem Fehler und einer>>> Warnung, wenn man eine Warnung wie einen Fehler behandeln soll?>>>> Dass man sich darum kümmert die Warnung zu beseitigen.
Ich sehe da nicht, dass ich schrieb man solle Fehler nicht beseitigen.
Hab vielleicht was auf der Brille.
Rolf M. schrieb:> Wenn du das nicht so gemeint hast, ist ja ok,> dann kannst du das ja einfach sagen.
Das habe ich bereits mehrfach. Du solltest dir auch alles durchlesen was
ich schrieb. Ich zitiere nur mal die beiden nachfolgenden Post auf den
Post von mir, der anscheinend zur Verwirrung beitrug:
Dussel schrieb:> M. K. schrieb:>> Dass man sich darum kümmert die Warnung zu beseitigen.> Und den Fehler beseitigt man nicht? :DM. K. schrieb:> Bei dir laufen Programme obwohl der Compiler Fehler geworfen hat?> Beeindruckend, meiner macht da erst gar kein Hexfile draus. ;)
Und hieraus hast du jetzt ernsthaft interpretiert, dass ich sagte, dass
man Fehler nicht beseitigen soll? Faszinierend.
Rolf M. schrieb:> Weil noch andere Komponenten davon abhängig sind, und deren Ersteller> sich bedankt, wenn er die umprogrammieren muss wegen eines Parameters,> der eigentlich gar keine Rolle mehr spielt - nur damit ich keine Warnung> in meinem Code bekomme.
Na wenn der Parameter unbenutzt ist müssen auch andere ihren Code ändern
oder warum glaubst du dass deren Code keine Warnung ausgibt beim
Übersetzen?
Rolf M. schrieb:> Tja, wenn äußere Zwänge ihn nötig machen, gehört er eben hin. Leider> kommt dann aber eine Warnung, wenn man ihn nicht auch benutzt.
Tja, wenn es mal diese Zwänge gäbe…und nein, dein Beispiel zeigt eher,
dass du eine Funktion nicht so benutzen willst wie es vorgesehen ist.
Rolf M. schrieb:> Wie kommst du denn darauf? Wenn die Funktion den Parameter nicht mehr> benötigt, aber ansonsten ihre Arbeit einfach weiter ganz normal tut, was> soll sich dann an der API geändert haben?
Du hast meine Frage an dich gut erkannt ;)
Wenn der Parameter der Funktion nicht mehr benutzt wird muss sich ja die
Funktion der API geändert haben. Mal ein einfaches Beispiel:
1
intadd(inta,intb){
2
returna+b;
3
}
Was muss ich hier tun, dass b nicht mehr benutzt wird? Genau, ich muss
die Funktion ändern:
1
intadd(inta,intb){
2
returna;
3
}
Selbst wenn jetzt noch andere diese API benutzen und meinen sie würden
den Parameter b brauchen: Die Funktion ist ja auf einmal unabhängig von
b. Deren Programm würde also nicht mehr den Erwartungen entsprechen (man
würde ja erwarten, dass die Funktion von a und b abhängt), da ist es ja
sogar besser wenn der Compiler einen Fehler ausgibt statt nur ne
Warnung. Also den Parameter löschen und nicht den Code so ändern dass
die Warnung nicht mehr angezeigt wird.
Rolf M. schrieb:> Nein, das sieht er nicht, da Compiler keine künstliche Intelligenz> haben, die sowas erkennen könnte. Sie können nur nach einfachen Regeln> auf typische Stolperfallen prüfen und da pauschal warnen, ohne den> tatsächlichen Sinn oder Unsinn wirklich zu erkennen.
Richtig, und der Compiler sieht nur dass dein Code nicht den Regeln
entspricht.
Rolf M. schrieb:> Ok, hab ich getan und festgestellt: Ich hab hier das richtige gemacht.> Leider geht die Warnung davon nicht weg.
Falsch. Du hast eine Funktion mit einem Parameter den du nicht benutzt.
Das ist nicht das Richtige sondern das Falsche. Kümmere dich drum.
Rolf M. schrieb:> Natürlich gibt es falsche Warnungen. Die treten vor allem dann auf, wenn> der Compiler anfängt, an Stellen zu warnen, die eigentlich nicht falsch> sind sondern nur vielleicht falsch sein könnten.
Nein, es gibt keine falschen Warnungen. Es gibt Folgewarnungen/-fehler
weil man schon zuvor was falsch gemacht hat. Aber da sind wir dann schon
am Punkt dass sich nicht nur das Programm, dass man schreiben wollte,
sich nicht erwartungsgemäß verhält sondern schon der Quellcode eine
anderes Verhalten hat als das was man erwartet und das Ganze nur weil
man einen Fehler gemacht hat, weil man sich nicht an die Regeln gehalten
hat (warum auch immer)
Rolf M. schrieb:> ...quittiert gcc mit:> "error: parameter name omitted"> da es in C nicht gestattet ist, namenlose Parameter zu haben.
In C++ schon.
> Man muss einen völlig sinnlosen Quatsch hinschreiben, nur> um eine nutzlose Warnung wegzubekommen.
Sinnlos?
Schon der Quelltext sollte dem Leser zeigen, dass die Variable nicht
vergessen wurde, sondern absichtlich nicht benutzt wird. Das kann bspw.
durch Auslassen des Namens oder dem (void) cast geschehen.
Nutzlos?
Es stellt ein potentielles Problem dar. Ich möchte grundsätzlich darüber
informiert werden. Auch wenn es Situationen gibt wo das "nervt".
M. K. schrieb:> Falsch. Du hast eine Funktion mit einem Parameter den du nicht benutzt.> Das ist nicht das Richtige sondern das Falsche. Kümmere dich drum.
hast du schon Mal mit Callback Funktionen gearbeitet?
Beispielsweise übergibt eine Bildverabeitungsfunktion die Werte eines
Pixels:
int callback(int red, int green, int blue)
ich möchte aber jetzt nur die rot-Werte verarbeiten.
Was machst Du in dem Fall mit der Warnung des Compilers?
In C gibt es Errors statt Warnings. Dort halt mit (void) cast oder self
assignment. Das mag "nervig" sein sorgt aber nebenbei auch für selbst
dokumentierenden Code.
Paul B. schrieb:> Jeden Tag werde ich froher darüber, nicht C oder C-Ähnliches benutzen zu> müssen.>> SCNR> -Paul-
Dann müsstest du aber doch "SNR" schreiben. ;-)
M. K. schrieb:> Ich sehe da nicht, dass ich schrieb man solle Fehler nicht beseitigen.> Hab vielleicht was auf der Brille.M. K. schrieb:> Und hieraus hast du jetzt ernsthaft interpretiert, dass ich sagte, dass> man Fehler nicht beseitigen soll? Faszinierend.
Nicht daraus, aus dem davor Geschriebenen.
Entweder verstehst du es wirklich nicht, dann kann ich nicht weiter
helfen, weil alles zum Verstehen nötige schon ausführlich da steht, oder
du willst provozieren, dann kann ich auch nicht helfen, weil ich mich
davon nicht provozieren lasse.
Danke Rolf für die mehrfachen Erklärungsversuche.
Mikro 7. schrieb:> In C++ schon.
Ebenso in C# und PHP. Aber hier geht es ja um C.
M. K. schrieb:> Ich sehe da nicht, dass ich schrieb man solle Fehler nicht beseitigen.> Hab vielleicht was auf der Brille.
Indirekt schon. Jemand fragt dich, was der Unterschied zwischen einem
Fahrrad und einem Motorrad ist. Wenn du sagst, der UNTERSCHIED liegt
darin, dass ein Motorrad 2 Räder hat, bedeutet das gleichzeitig, dass du
glaubst ein Fahrrad hätte keine 2 Räder (mehr oder weniger oder keine).
Sonst wäre es ja kein Unterschied sondern eine Gemeinsamkeit. Wenn du
also sagst, der Unterschied zwischen Fehlern und Warnungen ist, dass
eine Warnung beseitigt werden soll, heißt es im Umkehrschluss, ein
Fehler soll nicht beseitigt werden. Sonst wäre es kein Unterschied. Ich
glaub aber auch, dass jeder weiß, dass du das so nicht gemeint hast,
sondern nur sagen wolltest, dass Warnungen im allgemeinen beseitigt
werden sollen, Fehler natürlich ebenso.
Walter S. schrieb:> int callback(int red, int green, int blue)>> ich möchte aber jetzt nur die rot-Werte verarbeiten.>> Was machst Du in dem Fall mit der Warnung des Compilers?
Der Fehler käme aber beim Aufruf, wenn dort nur der red-Parameter
übergeben wird. Wieso sollte hier green und blue in der Funktion nicht
benutzt werden sollen? Die 3 Parameter deuten ja darauf hin, dass alle 3
Farben bearbeitet werden. Dann wundert man sich ja nur, wenn das nicht
hinten raus kommt sondern die Parameter nur nicht benutzt werden.
Sollte jemand die Funktion schon mit RGB-Werten benutzt haben und der
Ersteller der Funktion ändert die Funktion so, dass nur Rot verarbeitet
wird und lässt die anderen Parameter drin (damit niemand fehler beim
compilieren bekommt), wundern sie diese, wieso nichts mit ihren Grün und
Blau-Werten passiert.
Jörg W. schrieb:> Walter S. schrieb:>> Was machst Du in dem Fall mit der Warnung des Compilers?> __attribute__((unused))
Schaltet das nicht die Warnung zu ALLEN unbenutzten Parametern/Variablen
aus? Das bringt ja nichts, wenn man sie nur an ein/zwei stellen explizit
haben will aber nirgends anders.
Paul B. schrieb:> Jeden Tag werde ich froher darüber, nicht C oder C-Ähnliches benutzen zu> müssen.>> SCNR> -Paul-
Ich frag mich schon wo Moby bleibt und schreibt "Ihr seid selber Schuld
C zu nutzen. Bei ASM gäbe es diese Frage nicht und die Programme wären
deutlich effizienter" ;)
Michael S. schrieb:> Sollte jemand die Funktion schon mit RGB-Werten benutzt haben und der> Ersteller der Funktion ändert die Funktion so, dass nur Rot verarbeitet> wird und lässt die anderen Parameter drin (damit niemand fehler beim> compilieren bekommt), wundern sie diese, wieso nichts mit ihren Grün und> Blau-Werten passiert.
Das Bildverarbeitungsprogramm wird sich nicht wundern wenn du nur die
rot-Werte verarbeitest weil dich grün und blau einfach nicht
interessieren
Michael S. schrieb:> M. K. schrieb:>> Ich sehe da nicht, dass ich schrieb man solle Fehler nicht beseitigen.>> Hab vielleicht was auf der Brille.>> Indirekt schon.
Ja, wenn man nur den einen Post liest ist das richtig. Darauf frug man
aber, ob man denn Fehler nicht beseitigen soll worauf ich fragte, ob
denn ein Programm laufen würde bei dem der Compiler Fehler meldete und
dann fing es an dass gesagt wurde ich hätte behauptet Fehler müsse man
nicht beseitigen.
Egal, ich denk da wahrscheinlich zu kompliziert.
Michael S. schrieb:> Der Fehler käme aber beim Aufruf, wenn dort nur der red-Parameter> übergeben wird. Wieso sollte hier green und blue in der Funktion nicht> benutzt werden sollen? Die 3 Parameter deuten ja darauf hin, dass alle 3> Farben bearbeitet werden. Dann wundert man sich ja nur, wenn das nicht> hinten raus kommt sondern die Parameter nur nicht benutzt werden.>> Sollte jemand die Funktion schon mit RGB-Werten benutzt haben und der> Ersteller der Funktion ändert die Funktion so, dass nur Rot verarbeitet> wird und lässt die anderen Parameter drin (damit niemand fehler beim> compilieren bekommt), wundern sie diese, wieso nichts mit ihren Grün und> Blau-Werten passiert.
Das sehe ich genauso!
Walter S. schrieb:> Das Bildverarbeitungsprogramm wird sich nicht wundern wenn du nur die> rot-Werte verarbeitest weil dich grün und blau einfach nicht> interessieren
Richtig, das Programm wundert sich nicht. Aber wenn Hans-Wurst die
Funktion liest denkt er vielleicht die Funktion verhält sich auch bei
unterschiedlichen Grün und Blauwerten anders und der wundert sich dann
wenn es Funktion wurscht wie die Grün- und Blauwerte sind. Da fragt man
sich: Kommt Hans-Wurst auf die Idee, dass jemand in der tollen Funktion
die Grün- und Blauwerte rausgeworfen hat und sucht da den Fehler oder
fragt sich Hans-Wurst ob er nicht selbst einen Fehler gemacht hat ;)
Also ich such die Fehler immer zuerst bei meinem Code. Es würde dauern
bis ich merke: "Hey, mein Code ist OK aber die API ist daneben." Vor
allem bei diesem Beispiel wo es ja in der Vergangenheit auch mal
funktioniert haben musste.
M. K. schrieb:> "Hey, mein Code ist OK aber die API ist daneben."
Das API ist nicht daneben. Vielmehr nutzt das Anwendungsprogramm nicht
alle Informationen, die ihm das API über die Callback-Funktion zur
Verfügung stellt. Dazu besteht aber auch kein Zwang.
Die nächste Callback-Funktion nutzt vielleicht nur den Grün- und den
Blauwert, die übernächste alle drei Farben. Soll deswegen das API 2³=8
Callback-Schnittstellen zur Verfügung stellen, damit man immer den exakt
passen Satz von Argumenten hat?
@ Yalu X. (yalu) (Moderator)
>Blauwert, die übernächste alle drei Farben. Soll deswegen das API 2³=8>Callback-Schnittstellen zur Verfügung stellen, damit man immer den exakt>passen Satz von Argumenten hat?
Spätestens HIER haben Leute keinen passenden Satz von Argumenten mehr
;-)
Yalu X. schrieb:> Das API ist nicht daneben. Vielmehr nutzt das Anwendungsprogramm nicht> alle Informationen, die ihm das API über die Callback-Funktion zur> Verfügung stellt. Dazu besteht aber auch kein Zwang.
Ist ja OK wenn das Anwendungsprogramm nicht alle Informationen der API
nutzt. Aber warum sollte dann ein Parameter einer Funktion einer API
unbenutzt sein? Ist ja OK wenn ich mich bei einer Funktion nur für das
Verhalten in Abhängigkeit von einer Variablen interessiere. Ich wüsste
jetzt aber auch nicht warum das ein Warning geben sollte.
Vielleicht kann mir das einer mal genau erklären.
M. K. schrieb:> Ich wüsste> jetzt aber auch nicht warum das ein Warning geben sollte.> Vielleicht kann mir das einer mal genau erklären.
Da gibts nicht viel zu erklären.... das ist einfach so...
Das GCC Handbuch sagt dazu:
> unused> This attribute, attached to a variable,> means that the variable is meant to be> possibly unused. GCC will not produce a> warning for this variable.
Aus: https://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Variable-Attributes.html
M. K. schrieb:> Ist ja OK wenn das Anwendungsprogramm nicht alle Informationen der API> nutzt.
Genau das ist aber eins der Beispiele, wo ein Funktionsargument
absichtlich unbenutzt bleibt. Da der Compiler diese Absicht aber nicht
erkennen kann, liefert er trotzdem eine Warnung. Also wird man per
void-Cast oder Selbstzuweisung versuchen, diese Warnung zu beseitigen.
Darum ging es doch in der Diskussion in den letzten paar Beiträgen,
oder?
> Aber warum sollte dann ein Parameter einer Funktion einer API> unbenutzt sein?
Was ist eine Funktion eines API? Ein API (Application Programming
Interface) ist eine Programmierschnittstelle und besteht nur aus
Funktionsproto- und Datentypen.
> Ist ja OK wenn ich mich bei einer Funktion nur für das Verhalten in> Abhängigkeit von einer Variablen interessiere. Ich wüsste jetzt aber> auch nicht warum das ein Warning geben sollte. Vielleicht kann mir das> einer mal genau erklären.
Diese Frage habe ich nicht verstanden.
Michael S. schrieb:> Wenn du> also sagst, der Unterschied zwischen Fehlern und Warnungen ist, dass> eine Warnung beseitigt werden soll, heißt es im Umkehrschluss, ein> Fehler soll nicht beseitigt werden. Sonst wäre es kein Unterschied.
Mein Lieber, dein logisches Denkvermögen braucht mal ein bissel
Erholung.
Also:
Der Unterschied zwischen Fehlern und Warnungen ist, daß Warnungen
beseitigt werden sollen. Fehler hingegen MÜSSEN beseitigt werden,
sonst gibt's keinen Objektcode, basta.
Es ist der Unterschied zwischen Sollen und Müssen.
Yalu X. schrieb:> Genau das ist aber eins der Beispiele, wo ein Funktionsargument> absichtlich unbenutzt bleibt. Da der Compiler diese Absicht aber nicht> erkennen kann, liefert er trotzdem eine Warnung.
Ja. Dir ist aber klar, daß dieses so langsam über die Grenzen von C
hinausgeht, denn typischerweise macht man Derartiges, wenn man sowas wie
objektorientieres Programmieren in C nachbildet. Da werden eben
innerlich unterschiedliche Objekte (hier in C eben schnöde Funktionen in
einem struct) mit gleichem Satz an Argumenten deklariert, eben DAMIT man
sie alle von außen auf die gleiche Weise aufrufen kann, auch wenn das
eine oder andere Argument in der einer der konkreten Funktionen nicht
Verwendung findet. Das sind Gefilde, mit denen klassisches C eben nicht
rechnet und folglich gibt es damit eben Reibereien.
Aber wir waren hier ursprünglich beim Thema GOTO - gelle?
Und eine Menge Leute ereifern sich, weil sie meinen, goto grundsätzlich
verdammen zu müssen. Klar, es gibt für fast alles einen Workaround,
siehe als klassisches Beispiel den MIPS-Befehlsumfang. Aber sowas wie
goto gehört seit jeher zur Grundausstattung der allermeisten
Programmiersprachen (mal rein Deklarative ausgenommen) und das aus
wirklich gutem Grund. Für die künstlich aufgesetzte Scheuklappe bzw.
Einengung des eigenen Horizonts durch imperatives Verdammen von Goto
sehe ich keinerlei Berechtigung. Nicht mal eine stichhaltige Begründung
gibt es dafür.
W.S.
In den ca. 20Jahren beruflicher embedded Programmierung gab es immer
einen Weg Konstrukte ohne goto, continue oder exit aufzubauen. Es ist
halt zeitaufwendiger und fordert auch ein gewisses Mass an Disziplin im
Gesamtkonzept.
Meines Erachtens ist goto nicht verpönt sondern in den meisten Fällen
nicht notwendig, zumindest nicht bei C. Ich behaupte auch mal, dass es
bei aktuellen Basic Dialekten nicht mehr zum guten Programmierstil
gehoehrt, sondern nur aus Bequemlichkeit verwendet wird!
visitor schrieb:> Meines Erachtens ist goto nicht verpönt sondern in den meisten Fällen> nicht notwendig, zumindest nicht bei C.
Ich würde sogar noch einen Punkt weiter gehen: goto ist in allen Fällen
nicht notwendig.
Bei geschickter Anwendung jedoch kann es den Code lesbarer machen (bei
so 10 ineinandere verschachtelter Schleifen/Bedingungen kann es schon
unübersichtlich werden).
M. K. schrieb:> Ich würde sogar noch einen Punkt weiter gehen: goto ist in allen Fällen> nicht notwendig. Bei geschickter Anwendung jedoch kann es den Code> lesbarer machen
Da war Donald Knuth schon 1974. :-)
(Damals gab es auch noch Effizienzgründe bspw. gegen die Verwendung
einer Hilfsvariablen. Die sind mittlerweile weitgehend entfallen,
da die Compiler besser sind als damals.)
M. K. schrieb:> Bei geschickter Anwendung jedoch kann es den Code lesbarer machen (bei> so 10 ineinandere verschachtelter Schleifen/Bedingungen kann es schon> unübersichtlich werden).
Wenn du 10 ineinander verschachtelte Schleifen und Bedingungen hast,
dann ist schon vorher etwas grundlegend falsch gemacht worden.
Die Lösung dazu sollte ein Redesign sein und kein Goto^^.
Grüße.
nicht"Gast" schrieb:> M. K. schrieb:>> Bei geschickter Anwendung jedoch kann es den Code lesbarer machen (bei>> so 10 ineinandere verschachtelter Schleifen/Bedingungen kann es schon>> unübersichtlich werden).>> Wenn du 10 ineinander verschachtelte Schleifen und Bedingungen hast,> dann ist schon vorher etwas grundlegend falsch gemacht worden.> Die Lösung dazu sollte ein Redesign sein und kein Goto^^.
Oder aber auch das Redesign mit Goto. *ich lach mich schlapp über diese
Diskussion hier*
nichtCler schrieb:> Oder aber auch das Redesign mit Goto
Das Problem ist aber nicht goto, sondern die zu vielen verschachtelten
Schleifen. Das kann gar nicht lesbar sein. Auch nicht mit gotos drin.
nichtCler schrieb:> *ich lach mich schlapp über diese> Diskussion hier*
gab schon schlimmere Diskussusionen hier :).
nicht"Gast" schrieb:> M. K. schrieb:>> Bei geschickter Anwendung jedoch kann es den Code lesbarer machen (bei>> so 10 ineinandere verschachtelter Schleifen/Bedingungen kann es schon>> unübersichtlich werden).>> Wenn du 10 ineinander verschachtelte Schleifen und Bedingungen hast,> dann ist schon vorher etwas grundlegend falsch gemacht worden.> Die Lösung dazu sollte ein Redesign sein und kein Goto^^.>>> Grüße.
10 ineinander geschachtelte Schleifen sind üblicherweise ein Zeichen
dafür dass beim Design irgendwo Murks gebaut wurde.
Im Endeffekt ist die Lösung dafür üblicherweise das Ganze in eine
Funktion zu stopfen und diese sauber mit einem return zu verlassen
wenn's notwendig wird das vorzeitig zu terminieren.
Heinz L. schrieb:> 10 ineinander geschachtelte Schleifen sind üblicherweise ein Zeichen> dafür dass beim Design irgendwo Murks gebaut wurde.>> Im Endeffekt ist die Lösung dafür üblicherweise das Ganze in eine> Funktion zu stopfen und diese sauber mit einem return zu verlassen> wenn's notwendig wird das vorzeitig zu terminieren.
Kannst du das nicht anders ausdrücken?^^
Du schreibst im Grunde das gleiche wie ich nur klingt es so, als ob du
mir widersprichst. Das ist echt gruselig :)
Heinz L. schrieb:> 10 ineinander geschachtelte Schleifen sind üblicherweise ein Zeichen> dafür dass beim Design irgendwo Murks gebaut wurde.
Echt? Also ich könnte mir durchaus vorstellen wenn A wahr ist dann
durchlaufe B und prüfe bei jedem Durchgang ob C erfüllt ist. Und so
etwas kann ich mir auch durchaus legitim als noch etwas komplexer
erachten. Von Murks würde ich da nicht sprechen.
Die "10" waren übrigens fiktiv. Und ja, ich kann auch kein Beispiel
liefern, wo nur ein goto als sinnvoll ist.
nicht"Gast" schrieb:> Die Lösung dazu sollte ein Redesign sein und kein Goto^^.
Sag das mal dem Quellcode deines Betriebssystems bzw. deren
Programmierer oder hast du dein eigenen Betriebssystem geschrieben ganz
ohne goto? ;)
M. K. schrieb:> Echt? Also ich könnte mir durchaus vorstellen wenn A wahr ist dann> durchlaufe B und prüfe bei jedem Durchgang ob C erfüllt ist. Und so> etwas kann ich mir auch durchaus legitim als noch etwas komplexer> erachten. Von Murks würde ich da nicht sprechen.> Die "10" waren übrigens fiktiv. Und ja, ich kann auch kein Beispiel> liefern, wo nur ein goto als sinnvoll ist.
Schreib den entsprechenden Code, ich schreib's dann in meine Version
davon um und wir lassen mal abstimmen was lesbarer ist.
Heinz L. schrieb:> Schreib den entsprechenden Code, ich schreib's dann in meine Version> davon um und wir lassen mal abstimmen was lesbarer ist.
Was war an
M. K. schrieb:> Und ja, ich kann auch kein Beispiel> liefern, wo nur ein goto als sinnvoll ist.
nicht verständlich?
Heinz L. schrieb:> Schreib den entsprechenden Code, ich schreib's dann in meine Version> davon um und wir lassen mal abstimmen was lesbarer ist.
Fang' doch bitte lieber an, die 10000e gotos in *BSD und Linux
umzuschreiben, wenn du denkst, dass du dir damit Freunde machst.
Die Zählung für FreeBSD hatte ich weiter oben präsentiert, hier noch
die für Linux:
Jörg W. schrieb:> Fang' doch bitte lieber an, die 10000e gotos in *BSD und Linux> umzuschreiben, wenn du denkst, dass du dir damit Freunde machst.> Die Zählung für FreeBSD hatte ich weiter oben präsentiert, hier noch> die für Linux:
und wieder... (seufz)
die Gotos im Linux Source werden dazu benutzt, um das fehlende error
handling in C auszugleichen. Ich denke nicht, dass irgend wer hier damit
ein Problem hat.
Was hier aber bisher an Beispielen kam bei denen goto die Lesbarkeit
verbesern soll, taugt nur zum Fußnägel schneiden. Die rollen sich beim
Betrachten gerne mal auf und sind gut erreichbar :)
Deswegen die Forderung einen beliebigen eigenen Code reinzustellen und
dann schauen wir mal, welcher ohne goto schlechter lesbar ist.
nicht"Gast" schrieb:> Deswegen die Forderung einen beliebigen eigenen Code reinzustellen und> dann schauen wir mal, welcher ohne goto schlechter lesbar ist.
Dem schließe ich mich an. Bitte ein Beispiel zeigen, welches kein
Spezialfall ist. Betriebssysteme sind ein Spezialfall, denn die meisten
Softwareentwickler werden in ihrem ganzen Leben keine einzige Zeile Code
dafür schreiben.
nicht"Gast" schrieb:> die Gotos im Linux Source werden dazu benutzt, um das fehlende error> handling in C auszugleichen.
Hast du auch alle 114601 davon einzeln kontrolliert?
Ich versteh' nicht, warum jemand dir hier die Berechtigung beweisen
müsste, ein bestimmtes Feature der Sprache gelegentlich zu nutzen,
wenn es zwei sehr prominente Opensource-Projekte erwiesenermaßen
10000- oder gar 100000fach benutzen. Es ist doch völlig egal, wofür
es der einzelne benutzt, allein diese Zahlen zeigen, dass es
gelegentlich durchaus sinnvoll sein kann, das so zu machen, statt
irgendwelche anderen Verrenkungen zu vollführen.
Und nein, Betriebssystemcode ist auch erstmal ganz normaler Sourcecode.
Es gibt nur wenige Dinge im Betriebssystemkern, die da eine großartige
Sonderbehandlung erfahren, und diese sind in aller Regel weitgehend
in der Infrastruktur (Headerfiles etc.) abstrahiert. Als Programmierer
schreibe ich dort erstmal C-Code im Rahmen eines vorgegebenen APIs.
(@Mark: Been there, done that.)
Alleine dass etwas benutzt wird, heißt noch nicht dass es so richtig
ist. Nicht einmal dann, wenn dies häufig geschieht. Häufige Verwendung
ist keine qualitative Wertung, sondern eine quantitative.
Es gibt zum Beispiel nicht wenige Programmierer, die ein Dutzend
Funktionalitäten in eine einzige Funktion packen. Jeder, der Ahnung von
Software-Design hat weiß, dass man so nicht programmiert.
Aber das ist ein generelles Problem von Software: Sie kann auch dann
funktionieren, wenn der Code eine schlechte Qualität aufweist. Und die
ultimative Metrik für Softwarequalität hat man noch nicht gefunden. Man
hat aber in den letzten Jahrzehnten durchaus Erkenntnisse gewonnen, wie
man es besser macht. Nur werden diese eben von vielen Programmierern
fröhlich ignoriert. ;-)
Karl schrieb:> Ob man also GOTO oder was anderes verwendet ist reine syntaktische> Kosmetik!
Ja, aber gerade die Anwendung dieser syntaktischen Kosmetik entscheidet
oft über Übersichtlicheit oder Chaos im Quellcode.
Wenn man die von höheren Programmiersprachen angebotenen syntaktischen
Konstrukte (While-, For-Schleifen) nur deswegen nicht nutzt, weil sie
redundant sind und durch primitivere (Goto) ersetzt werden können, kann
man auch gleich bei Assembler bleiben.
Jörg W. schrieb:> Hast du auch alle 114601 davon einzeln kontrolliert?
Ich geb ja zu, dass ich nur in so ca 60Dateien bisher geschaut habe und
von da aus ein wenig "interpoliert" ^^.
Du kannst dich ja mit Googleein wenig informieren. Die Diskussion um
goto im Kernel ist zielmich lebendig, wobei Linus und der harte Kern
natürlich eine, ich nenne es mal, gefestigte Meinung haben :)
Das hat z.B. Atmel so rausgebracht. Ich muss zugeben, dass die
Frameworks teilweise auch sehr zusammengeschustert sind, aber so wie
hier benutze -ich persönlich- goto schon mal sehr gerne.
Natürlich kann man klammern bis der Arzt kommt, aber übersichtlicher
finde ich das nicht. Bin aber lernwillig und maße mir nicht an, die
ultimatice Meinung zu haben.
Von daher wäre ein umschreiben wie oben angeboten sicher eine mögliche
Inspiration!
edit: und bitte kein flag einführen, was dann nach dem switch abgefragt
wird oder so was. Das hat für mich keinen Mehrwert an der Stelle
Für das error Handling macht goto Sinn, siehe z.B die Linux
Treiberprogrammierung. Auch bei der Programmierung endlicher Automaten
gibt es sinnvolle Modelle welche mit goto realisiert werden. Ansonsten
wage ich zu behaupten Finger weg von goto!
Heinz L. schrieb:> Clemens, das ist auch wieder was das darum bettelt in eine Funktion> verpackt zu werden und über den Rückgabewert Erfolg oder Misserfolg zu> liefern.
Eben. Wenn man sowieso immer an die gleiche Stelle springt und da immer
das gleiche tut, dann kann man den Code für diesen Fall doch auch gleich
in einer Funktion kapseln.
Also das ist nun wirklich kein Beispiel in dem goto sinnvoll ist.
M. K. schrieb:> Was muss ich hier tun, dass b nicht mehr benutzt wird? Genau, ich muss> die Funktion ändern:> int add (int a, int b){> return a;> }>> Selbst wenn jetzt noch andere diese API benutzen und meinen sie würden> den Parameter b brauchen: Die Funktion ist ja auf einmal unabhängig von> b. Deren Programm würde also nicht mehr den Erwartungen entsprechen (man> würde ja erwarten, dass die Funktion von a und b abhängt)
Es gibt Fälle, wo ein Parameter stehen bleiben muß oder besser sollte,
obwohl er eigentlich nicht mehr benutzt wird. Ich habe ein Programm
geschrieben, wo unter anderem die Messunsicherheit berechnet wird. Diese
ist von verschiedenen Parametern abhängig, unter anderem von der
Temperatur am Anfang der Messung und am Ende der Messung. Jetzt hat sich
die ISO zur Berechnung der Unsicherheit geändert und die Temperatur am
Ende der Messung wird nicht mehr berücksichtigt. Demzufolge fällt sie in
der Berechnungsformel weg, d.h. sie ist für die Berechnung nicht mehr
notwendig. Obwohl dieser Parameter wegfällt gibt die Funktion immer noch
die berechnete Unsicherheit zurück. Das Programm ist sehr groß und ich
müßte den Aufruf an vielen Stellen ändern. Die Funktion ist in einer
eigenen Unit/Codedatei implementiert und wird auch von anderen
Programmen benutzt. Zudem wird diese Funktion auch von einer DLL für
andere Programme bereitgestellt. Jetzt müßte also jeder der diese DLL
benutzt seinen Quelltext ändern. Das ist viel zu aufwändig und hier
dürfte es wohl der bessere Weg sein die Warning zu ignorieren.
Karl schrieb:> Die ganze Diskussion ist sinnlos. wie man an den Ursprüngen von Fotran> sehen kann sind alle Schleifen und Zweige nur verkappte> GOTO-Anweisungen.
Karl hat es auf den Punkt gebracht. Eigentlich sind alle Schleifen und
Verzweigungen letzendlich GOTO's und wenn man sich den generierten
Assemblercode anschaut, dann werden solche Sachen i.d.R. in
Sprunganweisungen umgesetzt und ob ich nun sage "springe zu A" oder
"Gehe zu A" ist im Endeffekt das Gleiche.
Den schlechten Ruf hat sich GOTO eigentlich nur durch Basic eingefangen.
Z.B. gab es in den Fortrandialekten der Endsiebziger keine vernünftigen
Kontrollstrukturen, so daß dort zwingend mit GOTO gearbeitet werden
mußte.
Wenn man gewisse Dinge (z.B. nicht aus while-, for-,
switch/case-Schleifen oder Funktionen herausspringen) beachtet spricht
nichts gegen GOTO.
Es gibt Situationen wo der Einsatz von GOTO durchaus sinnvoll und alles
andere nur Krampf ist, auch wenn dies sehr sehr selten der Fall ist. Ja
und es gibt keinen Grund warum sich wegen des Einsatzes von GOTO schämen
müßte.
Zeno
Zeno schrieb:> Eigentlich sind alle Schleifen und> Verzweigungen letzendlich GOTO's und wenn man sich den generierten> Assemblercode anschaut, dann werden solche Sachen i.d.R. in> Sprunganweisungen umgesetzt und ob ich nun sage "springe zu A" oder> "Gehe zu A" ist im Endeffekt das Gleiche.
Jawoll!
Lange hat es gedauert, bis diese Wahrheit ausgesprochen wurde.
MfG Paul
Mich wundert immer wieder, welche alten Kamellen hier diskutiert werden.
Das Thema ist doch jetzt wirklich durch und dieses Forum wird vermutlich
außer persönlichen Meinungen nicht den Stein der Programmierer finden,
Um trotzdem nicht als reiner Nörgler dazu stehen:
Der verlinkte Artikel beschreibt das eigentliche Problem dahinter recht
gut:
http://www.drdobbs.com/jvm/programming-with-reason-why-is-goto-bad/228200966
Gruß
Marc
Mark B. schrieb:> Bitte ein Beispiel zeigen, welches kein> Spezialfall ist. Betriebssysteme sind ein Spezialfall, denn die meisten> Softwareentwickler werden in ihrem ganzen Leben keine einzige Zeile Code> dafür schreiben.
Ach, wo sind wir hier eigentlich???
Ja, im Mikrocontroller-Forum. Eben.
Was wir hier schreiben, IST Betriebssystem - nämlich die Firmware für
einen µC. Ich räume ein, daß es sich zumeist um ganz kleine
Betriebssysteme handelt, viel kleiner als das, was auf viel größeren
Anlagen läuft.
Aber es ist dennoch ein Betriebssystem und ich hatte ein richtig
zutreffendes Beispiel mit dem GOTO in der Grundschleife von main
gepostet.
Dort gehört das hin, weil damit der logische Knackpunkt beseitigt ist,
der sich zwischen dem niemals Zurückkehren und dem aus Prinzip
eingeforderten Returnwert auftut. So nebenher zeigt uns dieses Beispiel,
daß die millionenfach geübte Praxis, auf einem µC überhaupt ein main zu
haben, durchaus auf den Prüfstand gehört. Alternativ, ob main auf dem µC
überhaupt int sein muß oder besser void.
W.S.
W.S. schrieb:> Ach, wo sind wir hier eigentlich???>> Ja, im Mikrocontroller-Forum. Eben.>> Was wir hier schreiben, IST Betriebssystem
Das sehe ich anders.
> - nämlich die Firmware für einen µC. Ich räume ein, daß es sich zumeist> um ganz kleine Betriebssysteme handelt, viel kleiner als das, was auf> viel größeren Anlagen läuft.
Auch bei mir ist die Vorlesung über Betriebssysteme nun schon diverse
Jahre her. Das war übrigens die Vorlesung, in der Du immer geschlafen
hast und ich nur selten ;-)
Aus dem Gedächtnis abgerufen hat ein Betriebssystem die folgenden
Aufgaben:
-Verwalten des Speichers
-Verwalten des Dateisystems
-Verwalten von Benutzern
-Verwalten von Prozessen
-Abstrahieren von Hardware durch Bereitstellung von Schnittstellen,
damit man auf eben diese Hardware zugreifen kann (z.B. PCI, ISA, RS232,
Tastatur, Maus, Display, ...)
> So nebenher zeigt uns dieses Beispiel,> daß die millionenfach geübte Praxis, auf einem µC überhaupt ein main zu> haben, durchaus auf den Prüfstand gehört. Alternativ, ob main auf dem µC> überhaupt int sein muß oder besser void.
Es mag vielleicht eine etwas unglückliche Konvention sein, dass main()
laut Standard zwingend einen Rückgabewert haben soll. Ich persönlich
hätte nichts gegen ein void main() einzuwenden.
Warum diese Eigenheit der Programmiersprache C für die Verwendung von
goto sprechen soll, erschließt sich mir nicht so recht.
Zeno schrieb:> Es gibt Situationen wo der Einsatz von GOTO durchaus sinnvoll und alles> andere nur Krampf ist, auch wenn dies sehr sehr selten der Fall ist.
Wir warten immer noch auf ein wirklich gutes Beispiel, welches diese
Aussage untermauert.
Mark B. schrieb:> Wir warten immer noch auf ein wirklich gutes Beispiel, welches diese> Aussage untermauert.
Warum soll ich jetzt auf Krampf ein Beispiel kreieren.
Und ob das dann wirklich gut ist steht schon mal wieder auf einem
anderen Blatt. Das entscheidet jeder eh für sich. Der der stur auf der
Nichtverwendung von GOTO beharrt, wird definitiv eine andere Lösung
finden und im Nachgang behaupten sie sei besser, allein schon deswegen
weil sie GOTO vermeidet - koste es was es wolle.
Im übrigen gebe ich W.S. recht, die FW auf dem µC ist schon ein kleines
Betriebssystem, denn es werden sehr wohl die Hardwareressourcen (Ports,
Speicher etc.) verwaltet. Letztendlich wird auch hier die Hardware
abstrahiert damit sie benutzt werden kann und wenn es nur ein simpler
Schalter ist der an einem Port angeschlossen ist. Natürlich werden auf
dem µC keine Benutzer verwaltet und ja es werden auch keine Prozesse
verwaltet, weil nur ein Prozess nämlich die FW selbst läuft.
DOS verwaltetet(e) auch keine Benutzer und es lief i.d.R. auch nur ein
Prozess und es war dennoch ein BS.
Zeno
>Aus dem Gedächtnis abgerufen hat ein Betriebssystem die folgenden>Aufgaben:>-Verwalten des Speichers>-Verwalten des Dateisystems>-Verwalten von Benutzern>-Verwalten von Prozessen
<-Abstrahieren von Hardware
Das kann, muss aber nicht.
Genaugenommen sind auch "kleine" uC-Programme, die ohne Aufsatz laufen,
Betriebssysteme, mehr oder weniger komplex.
>Wir warten immer noch auf ein wirklich gutes Beispiel, welches diese>Aussage untermauert.
Wie schon geschrieben, bsp. mehrere if-Abfragen hintereinander, ohne
expliz. Schachtelungen, mit gemeinsamen Sprungziel.
MCUA schrieb:> Wie schon geschrieben, bsp. mehrere if-Abfragen hintereinander, ohne> expliz. Schachtelungen, mit gemeinsamen Sprungziel.
Warum sollte das Sprungziel keine eigenständige Funktion sein? Was
spricht dagegen?
Clemens M. schrieb:
[Wieder ganz viel Mist gelöscht]
> Das hat z.B. Atmel so rausgebracht. Ich muss zugeben, dass die> Frameworks teilweise auch sehr zusammengeschustert sind, aber so wie> hier benutze -ich persönlich- goto schon mal sehr gerne.
Hier sieht man wieder zwei Dinge:
a.) Wie oft und durch wen irgendetwas vorgemacht wird, sagt nichts, aber
auch gar nichts über Qualität aus.
b.) Auch das ist wieder ein Beispiel dafür, dass "goto" schwache
Programmierer zur dunklen Seite lockt.
> Von daher wäre ein umschreiben wie oben angeboten sicher eine mögliche> Inspiration!>> edit: und bitte kein flag einführen, was dann nach dem switch abgefragt> wird oder so was.
Wie immer, die Lösung ist so extrem simpel:
Ihr diskutiert am Thema vorbei. Ob Betriebssystem, Applikation, Rtos,
HAL, Treiber, APP, Skript usw ist doch vollkommen egal.
Ziel sollte sein Code zu schreiben, der funktioniert und möglichst
einige Qualitätskriterien erfüllt. Z.B.visuell schnell verständlich ist,
damit ein anderer Programmierer (oder man selber) in ein paar Monaten
Anpassungen machen kann ohne sich ins Knie zu schießen.
Und natürlich gibt es tausend mögliche Lösungen und natürlich kann ich
mit Goto chaotischen Code erstellen aber vielleicht auch für ein
spezielles Problem damit übersichtlichen Code erzeugen.
goto bedroom;
Programmierer schrieb:> Wie immer, die Lösung ist so extrem simpel:
Wirklich übersichtlicher ist Dein Code nicht. Du verzichtest halt auf
das goto - das ist alles.
Marc schrieb:> Und natürlich gibt es tausend mögliche Lösungen und natürlich kann ich> mit Goto chaotischen Code erstellen aber vielleicht auch für ein> spezielles Problem damit übersichtlichen Code erzeugen.
Genau so sehe ich das auch!
Clemens M. schrieb:> void usb_process_request(void)> {> U8 bRequest;>> Usb_reset_endpoint_fifo_access(EP_CONTROL);> bmRequestType = Usb_read_endpoint_data(EP_CONTROL, 8);> bRequest = Usb_read_endpoint_data(EP_CONTROL, 8);>> // jede menge komischer Code> }
Mal ne Frage. Was ist den vbmRequestType und wozu gibt es zwei Variablen
wenn von der zweiten Variablen anscheinend nur ein Wert vernünftig sein
kann? Die ganzen magic Numbers im Code machen das Verstehen so ziemlich
unmöglich. Damit kann man das Ganze ja auch nicht vernünftig
umschreiben.
Zu dem, jedes Programm auf einem µC ist ein Betriebssystem, Thema...
https://de.wikipedia.org/wiki/Betriebssystem
nope, ists nicht.
PS: Speicher benutzen heißt nicht, ihn zu verwalten.
nicht"Gast" schrieb:> Mal ne Frage. Was ist den vbmRequestType und wozu gibt es zwei Variablen> wenn von der zweiten Variablen anscheinend nur ein Wert vernünftig sein
Also von der 2. Variable gibt es mindestens 11 verschiedene Werte (s.
Post mit Orginalcode, zähle mal die case durch).
vbmRequestType habe ich nirgendwo gefunden. Du meinst sicher
bmRequestType. Da es sich hier um ein Codefragment handelt wird's schon
irgendwo im Quelltext deklariert sein.
@Programmierer: Da siehste es doch schon! Bei Deinem if-Gewurschtel geht
die Übersicht verloren. Hätte sich "nicht Gast" mal den Orginalquelltext
angesehen wäre ihm sofort aufgefallen das bRequest mehr als einen
vernünftigen Wert hat, sofern er das switch/case Konstrukt richtig
verstanden hat, was ich allerdings bezweifle, wenn ich dies
nicht"Gast" schrieb:> Die ganzen magic Numbers im Code machen das Verstehen so ziemlich> unmöglich.
lese. Denn das bedeutet für mich, daß er keine Hexzahlen kennt und
deshalb den Vergleich der Variable bmRequestType mit selbigen nicht
versteht.
Ich glaube da liegt ein Missverständnis vor: ich habe den Eindruck, dass
der eine oder andere davon aus geht, dass das was ich gepostet habe für
mich der Weisheit letzter Schluss ist. Das ist nicht so. Es steht halt
nur regelmäßig die Frage im Raum, wo goto außerhalb vom Linux Kernel zu
finden ist. Das ist ein Beispiel.
Ein Programmierer hat auch den Code umgeschrieben. Aber nur formal. Ich
kann jetzt wirklich nicht sagen, dass ich das übersichtlicher finde. Ist
Im Grunde doch das Selbe. Müsste jeder zugeben, außer dass man sich
bemüht hat eben aus Prinzip kein goto zu benutzen. Lesbarer ist es auch
nicht und die goto Verweigerer müssten eigentlich auch mal sagen, warum
jetzt die goto Variante schlechter ist - außer dass ein goto enthalten
ist.
Mit "magic number" ist sicherlich nicht hex Notation gemeint, sondern
die Verwendung von Konstanten, die nicht vom Präprosessor aus Klartext
erzeugt werden. Sprich jede "magic number" sollte vermutlich in einem
header stehen. Kann man aber auch wieder sehr gut drüber streiten.
Zeno schrieb:> Es gibt Fälle, wo ein Parameter stehen bleiben muß oder besser sollte,> …> Jetzt müßte also jeder der diese DLL> benutzt seinen Quelltext ändern. Das ist viel zu aufwändig und hier> dürfte es wohl der bessere Weg sein die Warning zu ignorieren.
Und was spricht dagegen, dass die, die diese DLL benutzen, eine ältere
Version der DLL benutzen so dass ihre Programme weiterhin funktionieren?
Mal ganz davon ab, z.B. die Youtube-API hat Google auch einfach so mal
geändert. Es hat Google nicht interessiert, dass jeder sein Programm
deshalb umschreiben mussten wenn es weiterhin funktionieren sollte. Das
also dann andere ihre Programme umschreiben müssten ist ein sehr
schwaches Argument.
Zeno schrieb:> @Programmierer: Da siehste es doch schon! Bei Deinem if-Gewurschtel geht> die Übersicht verloren. Hätte sich "nicht Gast" mal den Orginalquelltext> angesehen wäre ihm sofort aufgefallen das bRequest mehr als einen> vernünftigen Wert hat, sofern er das switch/case Konstrukt richtig> verstanden hat, was ich allerdings bezweifle, wenn ich dies
Das If gewurschtel habe ich gar nicht gelesen. Ist auch nur gewurschtel.
Warscheinlich habe ich mich nur falsch ausgedrückt. In jedem Request
wird nur ein RequestType geprüft. Wozu ist der RequestType gut?
Zeno schrieb:> lese. Denn das bedeutet für mich, daß er keine Hexzahlen kennt und> deshalb den Vergleich der Variable bmRequestType mit selbigen nicht> versteht.
Ernsthaft?
Warscheinlich hast du eher keine Ahnung wovon ich schreibe.
https://de.wikipedia.org/wiki/Magische_Zahl_(Informatik)#Magische_Zahlen_in_Code
Wenn er nicht gleich zu dem Absatz springt, dann scroll mal zu Magische
Zahlen in Code runter.
Jörg W. schrieb:> Hast du auch alle 114601 davon einzeln kontrolliert?
Hast du? ;)
Mark B. schrieb:> Alleine dass etwas benutzt wird, heißt noch nicht dass es so richtig> ist. Nicht einmal dann, wenn dies häufig geschieht. Häufige Verwendung> ist keine qualitative Wertung, sondern eine quantitative.
Find ich auch. Gibts eigentlich vergleichbare Statistiken von Windows
oder MAC OS? Vermutlich nicht, da kein Open Source.
Zeno schrieb:> Karl hat es auf den Punkt gebracht. Eigentlich sind alle Schleifen und> Verzweigungen letzendlich GOTO's und wenn man sich den generierten> Assemblercode anschaut, dann werden solche Sachen i.d.R. in> Sprunganweisungen umgesetzt und ob ich nun sage "springe zu A" oder> "Gehe zu A" ist im Endeffekt das Gleiche.
Was der Compiler daraus macht ist doch egal. Eine Hochsprache ist ja
hauptsächlich dafür da, den Maschinencode bzw Assemblercode zu
abstrahieren. Wieso sollte ich dann also so nah wie möglich noch am
compilierten Maschinencode bleiben?
Es schreibt doch (hoffentlich) keiner eine Schleife so:
1
Schleifenbedingung:
2
3
if(Bedingung_erfüllt){
4
gotoSchleifenbeginn;
5
}
6
gotoSchleifenende;
7
8
Schleifenbeginn:
9
// Schleifeninhalt
10
gotoSchleifenbedingung;
11
Schleifenende:
, auch wenn das quasi dem compilierten while entspricht. Derjenige
müsste dann ja (auf 8bitter µC) konsequenter Weise Zahlen vorher in 8bit
Breite Elemente auftrennen und separat berechnen. Das ist doch irgendwie
quatsch ;)
Am besten überlässt man es dem Compiler, wo er welchen Maschinenbefehl
setzt. Er oder Sie wird es am besten wissen.
Zeno schrieb:> @Programmierer: Da siehste es doch schon! Bei Deinem if-Gewurschtel geht> die Übersicht verloren.
Ich finde ihn nicht unübersichtlicher. Ich hätte den 2-Zeiler mit "else
if(bRequest == SET_INTERFACE ..." noch vor den vorherigen "else
if"-Block gesetzt, damit alle 2-Zeiler untereinander stehen, aber das
ist auch alles Geschmackssache.
Was ich besser finde ist: der umgeschriebene Code passt auf eine Seite,
man muss nicht scrollen um alles zu sehen und ist dabei trotzdem noch
gut lesbar, eingerückt usw. Außerdem hat er nur eine
Verschachtelungstiefe (if, else if und else). So kann man sich von einer
Bedingung zur nächsten Hangeln und sieht auf anhieb den einzelnen
Befehlsaufruf, der ausgeführt wird, sofern die Bedingung erfüllt ist.
Beim Original sind es 2 Ebenen. D.h. wenn der Cursor in die Mitte
positioniert wird, weil da z.B. ein Suchergebnis ist (man sucht z.B.
nach "usb_set_address();" ) und man will nun wissen, wann der aufgerufen
wird, muss erstmal hochgescrollt werden, um zu wissen, welche Variable
denn im Switch() steht, wieder runter scrollen um die nächste Bedingung
zu sehen und dann nochmal runter scrollen, um zu gucken, wann denn die
Sprungmarke kommt (wärend man hofft in die richtige Richtung zu
scrollen), zu der gesprungen wird, sollte die Bedingung nicht true sein.
Hier könnte man die Suche erleichtern, in dem man die Sprungmarke nach
ganz links setzt, wie auch in ASM, im Beispiel aber nicht der Fall.
Aber nochmal: Das ist alles Geschmackssache, weshalb es keine richtige
und falsche Meinung gibt. Und ich halte mich auch nicht für einen
unfehlbaren Programmierer (zumal das nicht mein Hauptjob ist) der
behaupten könnte, dass ein goto in keinem Fall angebracht ist (wo glaube
ich bisher jeder zugestimmt hat). Ich für meinen Teil hatte bisher aber
noch nie den Fall, wo ICH ein goto für die bessere Wahl gehalten habe.
BTW: MSDN z.B. schreibt:
> It is good programming style to use the break, continue, and return statements> instead of the goto statement whenever possible. However, because the break> statement exits from only one level of a loop, you might have to use a goto> statement to exit a deeply nested loop.
Das wäre wohl so ein Fall
M. K. schrieb:> Und was spricht dagegen, dass die, die diese DLL benutzen, eine ältere> Version der DLL benutzen so dass ihre Programme weiterhin funktionieren?
Dann würden die aber nicht mehr eine Berechnung nach (aktueller) ISO
haben.
M. K. schrieb:> Das also dann andere ihre Programme umschreiben müssten ist ein sehr> schwaches Argument.
Naja.. Die Funktion wird eh geändert. Und die Parameter drin zu lassen
und vlt ein (void)var zu spendieren ist bei weitem nicht so Aufwendig,
Zeitintensiv (vielleicht 10 Sekunden) und somit teuer, wie alle zu
benachrichtigen, die sich dann auch nochmal dransetzen müssen, alle
Dateien durchsuchen müssen und dann umschreiben, neu Kompilieren und ggf
testen oder auf Messplätze aufspielen (vielleicht 1-2 Tage PRO
Entwickler). Hier macht das für mich schon Sinn.
Anders ist es natürlich, wenn einen die anderen Programmierer nicht die
Bohne jucken. Dann kann man eben sagen: Ändert eure Programme. Hier
finde ich ja die optionalen Parameter super. So laufen noch alte
Programme aber neue müssen keinen Dummy-Parameter eingeben.
nicht"Gast" schrieb:> Warscheinlich habe ich mich nur falsch ausgedrückt. In jedem Request> wird nur ein RequestType geprüft. Wozu ist der RequestType gut?
Lies dir die USB spec durch, dann weißt du, warum es da zwei
verschiedene Dinge gibt.
Ich habe sowas auch schon runtergerattert (siehe µracoli-Projekt),
in diesem Falle ohne “goto”. Allerdings habe ich dort die
Fehlerbehandlung beim Aufrufer gemacht und dafür jede Menge
premature return im Code, die es natürlich nach der „reinen Lehre“
genauso wenig geben dürfte. Ist bloß 'ne andere Art “goto”.
Nennenswert übersichtlicher ist weder das eine noch das andere und
auch nicht das obige if/else-Gewurschtel.
nicht"Gast" schrieb:> Ernsthaft?> Warscheinlich hast du eher keine Ahnung wovon ich schreibe.> https://de.wikipedia.org/wiki/Magische_Zahl_(Informatik)#Magische_Zahlen_in_Code
So wie Du Dich ausgedrückt hast mußte ich davon ausgehen, daß Du nicht
mit Hex-Zahlen kannst.
Auch wenn in der von Dir zitierten Quelle von schlechten Stil gesprochen
wird, so empfinde ich das noch lange nicht so. Klar kann ich das auch in
einem Konstantenausdruck hinterlegen, aber dann brauch ich die passende
"Tabelle" um zu verstehen was da passiert.
Also ich habe mit "Magic Numbers" kein Problem.
Michael S. schrieb:> umgeschriebene Code passt auf eine Seite
Das ist ein ganz schlechtes Argument gegen GOTO, 1 - 2 Statements mehr
und der Code paßt nicht mehr auf eine Seite.
Michael S. schrieb:> M. K. schrieb:>> Und was spricht dagegen, dass die, die diese DLL benutzen, eine ältere>> Version der DLL benutzen so dass ihre Programme weiterhin funktionieren?>> Dann würden die aber nicht mehr eine Berechnung nach (aktueller) ISO> haben.
Richtig erkannt!
Zeno schrieb:> Also ich habe mit "Magic Numbers" kein Problem.
Wenn man nach dem Motto "Nach mir die Sinnflut" programmiert, dann kann
man natürlich beliebiges machen. Dann kannst du auch gerne mit gotos um
dich werfen, bis du selber nicht mehr druchblickst.
Genau darum geht es aber hier. Nachvollziehbarkeit von Quellcode. Nur
aus diesen Grund ist goto bei den Meisten verpönt. Technische Gründe hat
das keinen. Aber das haben die Paradigmen in der Programmierung nun mal
gemein.
Michael S. schrieb:> Dann würden die aber nicht mehr eine Berechnung nach (aktueller) ISO> haben.
Sie sind also sowieso gezwungen ihr Programm zu ändern...
Michael S. schrieb:> Hier> finde ich ja die optionalen Parameter super.
Kann C leider nicht wirklich gut. Bin auch ein großer Freund optionaler
Parameter. Macht das Programmieren leichter, wenn man im Nachgang was
ändern kann ohne alle Funktionsaufrufe anpassen zu müssen.
nicht"Gast" schrieb:> Wenn man nach dem Motto "Nach mir die Sinnflut" programmiert
Was bitte ist der Unterschied zwischen
1
a=b&0x02;
und
1
#define igend_etwas 0x02
2
3
....
4
5
a=b&irgend_etwas;
6
....
Wenn ich die #define-Zeile nicht sehe dann ist die Gleichung nicht
besser lesbar, bloß weil ich eine Konstante hinschreibe. Im Gegenteil!
Im ersten Beispiel sehe ich sofort das b mit 2 ver"und"et wird und a
ergibt. Im zweiten Beispiel muß ich mir den Konstantenparameter über das
#define erst erschließen, aber da weis ich trotzdem nicht wozu das gut
ist. Wenn man's ganz sauber macht gehört dann ein Kommentar dazu
entweder zum #define oder zur Gleichung.
Zeno schrieb:> Im Gegenteil! Im ersten Beispiel sehe ich sofort das b mit 2 ver"und"et> wird und a ergibt.
Allerdings interessiert dich normalerweise beim Lesen nicht, welches
Bit da nun genau erfragt wird. Vergleiche mal obigen Code mit dem
hier:
Ich denke, selbst ohne Kenntnis des USB-Standards kannst du aus dem
Code mit „benamsten“ Konstanten besser erkennen, was da gerade
erfragt wird, und wie dann die Antwort zustande kommt.
p.s.: Ich bin gewiss kein Freund der „Ungarischen Notation“. Die
Namen der Variablen mit ihrem „bXXX“, „bmXXX“ oder „wXXX“ entsprechen
einfach 1:1 den Feldnamen, die im USB-Standard so stehen. Das
erleichtert es einem Uneingeweihten, sich bei Bedarf schnell darin
zurechtzufinden, indem er sich eben den Standard danebenlegt.
Zeno schrieb:> Im zweiten Beispiel muß ich mir den Konstantenparameter über das> #define erst erschließen, aber da weis ich trotzdem nicht wozu das gut> ist.
Fast immer interessiert die konkrete Zahl überhaupt nicht. Das ist ein
Flag, eine Pin-Nummer,... Du durchsuchst jedesmal dein ganzes Projekt,
um aus 0x02 ein 0x04 zu machen?
> Wenn man's ganz sauber macht gehört dann ein Kommentar dazu> entweder zum #define oder zur Gleichung.
Steht doch sogar in deinem Beispiel da: 'irgend_etwas'. Reicht!
Zeno schrieb:> nicht"Gast" schrieb:>> Wenn man nach dem Motto "Nach mir die Sinnflut" programmiert>> Was bitte ist der Unterschied zwischen>
1
a=b&0x02;
> und
1
#define igend_etwas 0x02
2
>
3
>....
4
>
5
>a=b&irgend_etwas;
6
>....
Zwei Dinge:
1.) Man kann und sollte die Konstante so benennen, dass aus dem Namen
ersichtlich wird wozu sie gut ist. Das macht das Verständnis des Codes
einfacher.
2.) Sollte sich der Zahlenwert mal ändern, dann passt man ihn an genau
EINER Stelle an. Und nicht an fünfzig.
Och menno,
da geht man einmal zum Essen und vormuliert eine gesalzene Antwort und
dann haben das schon drei Leute vorneweg genommen^^
PS: Wer Magic Numbers schon verteidigt (und bei denen ist sich die
Community eigentlich einig), der hat sich für eine Diskusion über goto
IMHO disqualifiziert.
nicht"Gast" schrieb:> PS: Wer Magic Numbers schon verteidigt (und bei denen ist sich die> Community eigentlich einig), der hat sich für eine Diskusion über goto> IMHO disqualifiziert.
Sehe ich auch so.
Ich glaube da brauchen wir nicht vom Threadthema abweichen.
Die allermeisten werden sich einig sein, dass wichtige Konstanten in
menschenlesbarer Form sinnvoll sind. Und doch, es stimmt, man kann da
drüber streiten.
Dennoch möchte ich bitten einfach mal zu sagen, warum genau in dem
usb-Beispiel jetzt goto schlecht ist. Religiöse Gründe mal außen vor.
Viele wie Jörg haben da eine gesundere Haltung.
Jörg W. schrieb:> Allerdings habe ich dort die> Fehlerbehandlung beim Aufrufer gemacht und dafür jede Menge> premature return im Code, die es natürlich nach der „reinen Lehre“> genauso wenig geben dürfte. Ist bloß 'ne andere Art “goto”.
Finde ich nicht. Vom resultierenden Maschinencode mag das sein, doch bei
einem return weiß ich und jeder andere automatisch, dass die aktuelle
Funktion verlassen wird und vorallem, welchen Wert die Funktion zurück
gibt. Bei einem goto weißt man beides nicht.
Zeno schrieb:> Michael S. schrieb:>> umgeschriebene Code passt auf eine Seite>> Das ist ein ganz schlechtes Argument gegen GOTO, 1 - 2 Statements mehr> und der Code paßt nicht mehr auf eine Seite.
Es soll garkein Argument GEGEN goto sein. Es soll nur heißen, dass der
funktionell gleiche, aber umgeschriebene Code kürzer ist. Bei mehr
Unterscheidungen von bRequest wird der Unterschied der Zeilenanzahl
immer größer. Und mir gefällt das schlankere eben besser, weil dort bis
zu einem gewissen Grad noch alles auf eine Seite passt, wo es beim
anderen nicht mehr passt. Ich schreibe auch das "{" immer hinter das
if/while/... um eine Zeile zu sparen, weil ich es nicht weniger
übersichtlich finde. So können aus 1000 Zeilen Code auch mal schnell 900
werden, nur wenn man für das { keine eigene Zeile verwendet.
Der Unterschied in diesem Fall (mit dem "{" hinterm if) wäre 50 Zeilen
weniger. 50 Zeilen, die also gespart werden können, ohne die eigentliche
Funktion zu beeinflussen und (aus meiner Sicht) ohne dass die
Übersichtlichkeit drunter leidet. Es geht mir hier also nicht um goto
oder nicht, sondern um die Kompaktheit vom Code.
M. K. schrieb:> Michael S. schrieb:>> Dann würden die aber nicht mehr eine Berechnung nach (aktueller) ISO>> haben.>> Sie sind also sowieso gezwungen ihr Programm zu ändern...
Wieso das? Ein Programm läd die DLL, erfasst die Parameter, wirft die
Funktion aus der DLL an und zeigt das Ergebnis an oder sendet es zu
irgendeiner Art Protokollierung. Ändert sich diese Berechnung, ändert
sich die DLL, die geladen wird. Bei gleichen Funktionsnamen und gleichen
Parametern juckt das aber das Programm nicht. Man könnte höchstens
Argumentieren, dass es einen Mehraufwand gibt, einen Parameter zu
erfassen (Endtemperatur), der garnicht mehr begraucht wird. Sollte die
Messung aber parallel zu irgendwas laufen oder einfach Zeitlich kaum was
ausmachen, kann das eben vernachlässigt werden und bleibt drin. Dann
muss das eigentliche Programm bzw die Programme nicht geändert werden.
Zeno schrieb:> Kann C leider nicht wirklich gut. Bin auch ein großer Freund optionaler> Parameter. Macht das Programmieren leichter, wenn man im Nachgang was> ändern kann ohne alle Funktionsaufrufe anpassen zu müssen.
Meine ersten Programmiererfahrungen habe ich mit PHP gemacht, vor
Ewigkeiten. Da geht das auch, sogar ohne festgelegtem Datentyp. Man
konnte also einem Parameter, der für eine Zahl bestimmt war, den
Standardwert "FALSE" geben und in der Funktion mit is_numeric() prüfen,
ob es eine Zahl ist, also ob er (richtig) angegeben wurde oder nicht.
Clemens M. schrieb:> Dennoch möchte ich bitten einfach mal zu sagen, warum genau in dem> usb-Beispiel jetzt goto schlecht ist. Religiöse Gründe mal außen vor.> Viele wie Jörg haben da eine gesundere Haltung.
Die Inkonsistenz finde ich nicht gut. In den if-Pfaden wird jeweils eine
Funktion aufgerufen, in den else-Pfaden wird jeweils per goto
gesprungen. Wozu dieser Unterschied? Warum nicht einheitlich?
Ja, immer mit goto wäre dann auch einheitlich ;-)
Aber immer mit Funktionsaufrufen fände ich einfach besser.
@Clemens M. (panko)
>Dennoch möchte ich bitten einfach mal zu sagen, warum genau in dem>usb-Beispiel jetzt goto schlecht ist.
Es ist überflüssig, wenn gleich in diesem Fall nicht ultimativ schlecht.
Hier meine Variante ;-)
Je öfter ich darüberschaue, finde ich das Beispiel sogar immer besser:
Beitrag "Re: goto verpönnt - was dann nehmen?"
- Die gesamte Funktionalität ist innerhalb der 'switch'-Anweisung
- Wenn man den 'default'-Zweig (und dann sicher auch die beiden anderen
Konstanten) über ein gesetztes Flag außerhalb 'behandelt', meckert der
Compiler, dass möglicherweise nicht alle Fälle abgedeckt sind. So
bekommt man gleich noch die Warnung weg.
Ralf G. schrieb:> - Wenn man den 'default'-Zweig (und dann sicher auch die beiden anderen> Konstanten) über ein gesetztes Flag außerhalb 'behandelt', meckert der> Compiler, dass möglicherweise nicht alle Fälle abgedeckt sind. So> bekommt man gleich noch die Warnung weg.
Jedes switch hat auch einen default, wenn man richtig programmiert. Wo
soll da eine Warnung herkommen?
Mark B. schrieb:> Jedes switch hat auch einen default, wenn man richtig programmiert. Wo> soll da eine Warnung herkommen?
So steht wenigstens noch was drin :-)
Clemens M. schrieb:> Dennoch möchte ich bitten einfach mal zu sagen, warum genau in dem> usb-Beispiel jetzt goto schlecht ist. Religiöse Gründe mal außen vor.> Viele wie Jörg haben da eine gesundere Haltung.
Funktionell ist beides gleich. Daher kann man nicht sagen, dass die
"goto-Variante" schlechter/schlecht ist. Höchstens schlechter zu lesen,
zu verstehen oder nicht der allgemeinen Empfehlung entsprechend oder
keine Ahnung was noch. Aber das ist subjektiv.
Wenn ich es schlechter zu lesen finde, musst du das ja nicht auch so
sehen.
Mich würde mal interessieren, was an der umgeschriebenen Form "schlecht"
ist. Funktionell ist es ja identisch. Ich vermute, dass es viele nicht
so übersichtlich finden, so wie ich. Da sieht man mal wieder, dass es
Geschmackssache ist.
Das sieht immer so unfertig aus: Erstmal die Konstanten hinschreiben,
damit der Compiler zufrieden ist. Die zugehörige Funktionalität kommt in
der Testphase nach und nach dazu. Allerdings: Ich hätte es genauso
gemacht! Aber:
Ralf G. schrieb:> Je öfter ich darüberschaue, finde ich das Beispiel sogar immer besser:
Ralf G. schrieb:> Das sieht immer so unfertig aus: Erstmal die Konstanten hinschreiben,> damit der Compiler zufrieden ist. Die zugehörige Funktionalität kommt in> der Testphase nach und nach dazu. Allerdings: Ich hätte es genauso> gemacht!
Ja, das mache ich auch gerne so. Nur kann man da auch mal schnell die
implementation eines cases vergessen.
OT: da lob ich mir in C# meine lieblings Exception
(NotImplementedException ^^)
Dass man goto seltenst wirklich braucht ist sicher richtig.
Dass es allerdings auch nicht (wie öfter angedeutet oder explizit
gesagt) einem idiotischen Programmierer entspringt ebenso.
Dass es unterschiedliche Vorlieben gibt kann keiner bestreiten und dass
ganz konkret bei dem if-Grab und der goto Lösung keine messbare Aussage
über die Lesbarkeit getroffen werden kann entspricht der Subjektivität.
Falk hat jetzt noch eine Lösung gepostet. Die mit Flag. Die ist
natürlich naheliegend und auch deutlich besser lesbar als das if Ding.
(da ist für mich persönlich die Formatierung durch den switch erheblich
weiter vorne) Weil die so naheliegt hatte ich die oben 'indiziert'.
Es ist sogar denkbar, dass man Vorlieben im Laufe der Jahre ändert.
Stelle ich jedenfalls hin und wieder fest.
Ich finde einfach, dass es nie gut ist sich selber einem Dogma zu
unterwerfen und nicht offen und flexibel zu sein. Selbst die Leute die
gegen eine goto-Verwendung argumentieren müssen ja zugeben, dass sehr
oft nichts wirklich objektives dagegen spricht.
Ganz schlecht ist es wenn jemand nur blind Phrasen zitiert die er mal
gehört oder gelesen hat ohne sich selber eine Meinung zu bilden. Und da
läd die goto Debatte unschöner Weise zu ein.
Einfach die Aussage eines Professors (die dieser vermutlich auch
unreflektiert zitiert) lebenslang als gottgegeben hinzunehmen ist halt
unnötig.
Tjoar eigenltich ist alles gesagt, oder? Kann, aber lässt sich idR
vermeiden. Schadet aber auch nicht. Ist Geschmackssache.
Ach, vergessen.
das Problem an der einen Funktion (die aus der ASF) ist, dass sie
eingebettet ist.
Ich hätte erst das komplette SetupPaket in ein struct eingelesen und
erst dann and die einzelnen Funktionen übergeben.
dann sieht das ganze eher so aus:
Jörg W. schrieb:> Ich denke, selbst ohne Kenntnis des USB-Standards kannst du aus dem> Code mit „benamsten“ Konstanten besser erkennen, was da gerade> erfragt wird, und wie dann die Antwort zustande kommt.
Also erst mal sagen mir die benamsten Konstanten gar nichts und ich
erkenne nur das da da gegen irgend einen Wert verglichen wird.
Jörg W. schrieb:> Ich bin gewiss kein Freund der „Ungarischen Notation“. Die> Namen der Variablen mit ihrem „bXXX“, „bmXXX“ oder „wXXX“ entsprechen> einfach 1:1 den Feldnamen, die im USB-Standard so stehen.
Erst mit dem Wissen um den USB-Standard wird ein richtiger Schuh daraus.
Ich mußte mich bisher noch nicht damit befassen und kenne diesen deshalb
nicht.
Mit
1
b&0x02
hingegen sehe ich sofort, das an dieser Stelle die Variable b auf Bit1
abgeprüft wird.
Das heißt jetzt nicht das ich was gegen benamte Konstanten habe und bei
allgemeinen Standards machen diesen ja auch Sinn, aber wenn ich in einem
kleinen Programm auf ein bestimmtes Bit abprüfen will, dann schreibe ich
das in der Regel hin und zwar so wie oben beschrieben.
Zeno
Zeno schrieb:> Mit b & 0x02 hingegen sehe ich sofort, das an dieser Stelle die Variable> b auf Bit1 abgeprüft wird.
Das Wissen hilft dir aber rein gar nichts. Davon weißt du nicht,
ob das nun eine Anforderung an das Gerät, an die Klasse oder was
auch immer ist. Das müsstest du dann immer erst im Standard
nachlesen, während man es sich mit den Namen irgendwann merken kann,
was da so ungefähr läuft.
Aber lassen wir das, schreib' deine magischen Zahlen einfach weiter,
der Rest der Welt wird es eher nicht so haben wollen, und wir müssen
uns ja in deinen Code zum Glück nicht reinfinden.
Michael S. schrieb:> Bei gleichen Funktionsnamen und gleichen> Parametern juckt das aber das Programm nicht. Man könnte höchstens> Argumentieren, dass es einen Mehraufwand gibt, einen Parameter zu> erfassen (Endtemperatur), der garnicht mehr begraucht wird.
Genauso ist! Im übrigen wird (muß) um bei diesem Beispiel zu bleiben die
Endtemperatur weiterhin erfaßt werden, da sie dokumentiert werden muß.
Sie geht eben nur nicht mehr in die Berechnung ein. Wird zwar für manche
keinen Sinn machen, aber die DakkS-Richtlinien schreiben das so vor und
da wir ein akkrediertes Unternehmen sind, müssen wir uns an die
Richtlinien halten.
Zeno
Mark B. schrieb:> nicht"Gast" schrieb:>> PS: Wer Magic Numbers schon verteidigt (und bei denen ist sich die>> Community eigentlich einig), der hat sich für eine Diskusion über goto>> IMHO disqualifiziert.>> Sehe ich auch so.
Ihr seid schon 2 ganz schlaue. Ich deklariere wegen 2 3 Abfragen benamte
Konstanten, ich glaube es hackt. Da schreibe ich den Wert hin und
fertig. Das bedeutet ja nicht das man das generell so macht.
Keine magic Numbers zu benutzen ist genau so engstirnig wie GOTO
generell zu verteufeln.
Zeno
Zeno schrieb:> das an dieser Stelle die Variable b auf Bit1> abgeprüft wird.
Ja, aber da weißt du nicht warum das geprüft wird.
So ein Vergleich:
Prüfe Register 3, bit 4 ob es gesetzt ist und setze dann Register 2, bit
1 wäre doch sehr verwirrend. Besser wäre da doch
Prüfe ob an PortB der Taster A gedrückt ist und schalte dann an PortA
LED A ein.
Das wäre doch viel besser. Und genau sowas sollen doch benamte
Konstanten ermöglichen. Ist mir zumindest auch immer lieber als
irgendwelche Zahlenwerte ohne Bezug zu dem was sie repräsentieren.
M. K. schrieb:> Das wäre doch viel besser. Und genau sowas sollen doch benamte> Konstanten ermöglichen. Ist mir zumindest auch immer lieber als> irgendwelche Zahlenwerte ohne Bezug zu dem was sie repräsentieren.
Bestreite ich doch gar nicht und wenn man dann noch zu den Namen einen
Bezug herstellen kann ist doch alles chick.
Benamte Konstanten müssen aber deklariert sein um sie benutzen zu
können. Das tue ich entweder mit #define oder ich benötige die
Headerdatei wo die Konstante deklariert ist. In einem (sehr) kleinen
Projekt werde ich weder eine Headerdatei einbinden deren Länge das
eigentliche Projekt um ein vielfaches übersteigt noch werde ich eine
Konstante deklarieren, wenn ich diesen Wert nur an 1 - 2 Stellen
benötige. Da die meisten meiner Projekte privater Natur sind muß ich
mich an keine Dogmen binden - da muß nur ich den Code verstehen.
Wenn man was im Team macht ist das durchaus was anderes und dann hält
man sich an allgemeinen Regeln bzw. an die vom Team aufgestellten
Regeln.
Michael S. schrieb:> M. K. schrieb:>> Ich sehe da nicht, dass ich schrieb man solle Fehler nicht beseitigen.>> Hab vielleicht was auf der Brille.>> Wenn du> also sagst, der Unterschied zwischen Fehlern und Warnungen ist, dass> eine Warnung beseitigt werden soll, heißt es im Umkehrschluss, ein> Fehler soll nicht beseitigt werden. Sonst wäre es kein Unterschied. Ich> glaub aber auch, dass jeder weiß, dass du das so nicht gemeint hast,> sondern nur sagen wolltest, dass Warnungen im allgemeinen beseitigt> werden sollen, Fehler natürlich ebenso.
Wenn wir hier schon beim Korinthenkacken sind, dann bitte wenigstens
richtig: Fehler sollen nämlich nicht beseitigt werden, sondern Fehler
müssen beseitigt werden. Das unterscheidet sie von Warnungen, die nur
beseitigt werden sollen, aber nicht müssen.
Zeno schrieb:> In einem (sehr) kleinen Projekt werde ich weder eine Headerdatei> einbinden deren Länge das eigentliche Projekt um ein vielfaches> übersteigt
Dann wirst du aber nie einen AVR programmieren dürfen. Selbst bei
einem ATmega328P ist die Headerdatei für den Controller schon knapp
1000 Zeilen lang. Nach deiner Anforderung dürftest du folglich damit
kein Projekt von weniger als vielleicht 500 Zeilen anfangen …
Um mal Zenos Punkt zu stützen kann man auch wieder relativieren. Wie
immer im Leben.
1
uint32_ttimeout=tick_ms+100;
2
while(tick_ms<timeout){
3
(...)
4
}
5
6
gegen
7
#define TIMEOUT_MS 100
8
9
uint32_ttimeout=tick_ms+TIMEOUT_MS;
10
while(tick_ms<timeout){
11
(...)
12
}
Das kann auch in einem Header schnell unübersichtlich werden, wenn man
wirklich wieder ALLE numerischen Konstanten blind ersetzt.
kann schließlich so was werden:
1
#define TIMEOUT_UART_RX_MS 100
2
#define TIMEOUT_UART_TX_MS 100
3
#define TIMEOUT_USER_ENRY
4
#define TIMEOUT_BLA
5
#define TIMEOUT_BLUB
6
(....)
Würde ich im konkreten Fall entscheiden ob das jetzt Sinn macht. Ein
Dritter muss ja auch erst wissen, wo Timeouts abgefragt werden und falls
das nur einmalig ist wird der Header unübersichtlicher.
Aber was wieder unstreitbar ist, das ist die Tatsache, dass die nackte
Konstante 100 hier nicht mystisch ist.
Jörg W. schrieb:> Ich habe sowas auch schon runtergerattert (siehe µracoli-Projekt),> in diesem Falle ohne “goto”.
Bei diesem Projektnamen hätte ich eigentlich genau das Gegenteil,
nämlich ganz viele Gotos erwartet:
https://www.miracoli.de/
SCNR
chris_ schrieb:> Da der Thread immer länger wird, kennt Ihr den schon:> Beitrag ""goto"-Befehl in C"
Astrein. Keine Front hat sich verändert :) Goto ohne Tabs? Warum gehen
nicht einfach alle nach Hause? Fragen ihren Chef oder tun einfach statt
zu fabulieren.
Yalu X. schrieb:> Bei diesem Projektnamen hätte ich eigentlich genau das Gegenteil,> nämlich ganz viele Gotos erwartet:>> https://www.miracoli.de/
Tja, Namen sind halt Schall und Rauch. :-)
Nein, Axel hatte damals schon etwas recherchiert, nicht dass die
sich davon angep***t fühlen, aber das ist wohl erstens weit genug
weg von Nudeln, und zweitens ist „Miracoli“ ein ganz normales
italienisches Wort (bzw. ein Kasus dessen).
Mark B. schrieb:> Warum diese Eigenheit der Programmiersprache C für die Verwendung von> goto sprechen soll, erschließt sich mir nicht so recht.
Ähem.. nun ja, es liegt wohl an deinem etwas zu engen Horizont.
Siehe Adenauer:
"Wir leben alle unter dem gleichen Himmel, aber wir haben nicht alle den
gleichen Horizont."
Ich hatte die sachliche Begründung ja schon geschrieben, also lies
gründlicher.
W.S.
Michael S. schrieb:>> It is good programming style to use the break, continue, and return statements>> instead of the goto statement whenever possible.
OK Michael, das war ein Zitat und nicht von dir, nun ja.
Aber "whenever possible" ???
Das ist ne Unverschämtheit.
Da will mir ( MIR!! ) irgend jemand vorschreiben, was guter
Programmierstil ist. Und das soll sich darin ausdrücken, daß man alles
andere außer goto zu verwenden hat "whenever possible"? Dreistigkeit
sowas! Frechheit!
Nein, Zitate von solcher Machart braucht die Welt nicht.
W.S.
Jörg W. schrieb:> if (bmRequestType == (DIR_IN | RQTYPE_STANDARD | RQRCPT_DEVICE))> {> UEINTX &= ~_BV(RXSTPI);
Jörg, du willst sicherlich nicht behaupten, daß dieses Zitat lesbarer
sei als wenn dort mit schnöden (1<<xyz) gearbeitet worden wäre und
hinter dem Statement ein erhellender Kommentar stünde.
Also (ohne Anspruch auf Richtigkeit) etwa so:
UEINTX &= ~(1<<7); // reset für TX ein
Mir ist es elleweil ein Graus, wenn Programmierer in ihrem Bestreben,
sich besonders bedeutungsvoll auszudrücken, sich irgend eine Nomenklatur
ausdenken und darauf aufbauend abenteuerliche Namen erfinden. Deren
Bedeutung hat man nämlich nach 3 tagen vergessen und dann fängt das
Suchen zwecks Wiederverstehen an.
W.S.
Clemens M. schrieb:> Um mal Zenos Punkt zu stützen kann man auch wieder relativieren.
Endlich mal einer, der sich wenigstens bemüht einen anderen Denkansatz
nachzuvollziehen und nicht starr auf irgendwelchen Dogmen beharrt.
Clemens M. schrieb:> Aber was wieder unstreitbar ist, das ist die Tatsache, dass die nackte> Konstante 100 hier nicht mystisch ist.
Jetzt wird mir was klar: Ich hätte an Stelle von 0x02 lieber 4 schreiben
sollen, dann hätte es vielleicht die Diskussion so gar nicht gegeben. Da
wir uns hier aber in einem Mikrocontrollerforum befinden, bin ich davon
ausgegangen, das das Umrechnen einer kleinen Hexzahl in eine Dezimalzahl
kein Problem darstellt. Ich habe mich offensichtlich schwer getäuscht.
Aber ich bin ja schon froh das ich es nicht als Binärzahl oder Oktalzahl
geschrieben habe. Was hätte das wohl gegeben?
Zeno
W.S. schrieb:> Jörg, du willst sicherlich nicht behaupten, daß dieses Zitat lesbarer> sei als wenn dort mit schnöden (1<<xyz) gearbeitet worden wäre und> hinter dem Statement ein erhellender Kommentar stünde.> Also (ohne Anspruch auf Richtigkeit) etwa so:> UEINTX &= ~(1<<7); // reset für TX ein
Das Löschen des Interruptflags hätte man noch lesbarer machen können
(ist ja jedesmal dasselbe). Darum ging es nicht.
Es ging um den Teil davor:
DIR_IN | RQTYPE_STANDARD | RQRCPT_DEVICE
kann man, wenn man ein wenig in den USB-Standard geguckt hat, auch
nach einem Jahr noch sofort zuordnen, während man die Bitwerte nach
dieser Zeit getrost wieder vergessen hat.
Wenn dort stattdessen 0x47 steht, guckst du jedesmal im Standard nach.
Zeno schrieb:> Jetzt wird mir was klar: Ich hätte an Stelle von 0x02 lieber 4 schreiben> sollen, dann hätte es vielleicht die Diskussion so gar nicht gegeben. Da> wir uns hier aber in einem Mikrocontrollerforum befinden, bin ich davon> ausgegangen, das das Umrechnen einer kleinen Hexzahl in eine Dezimalzahl> kein Problem darstellt.
Ja, sollte man annehmen. Übrigens, 0x02 ist dezimal 2 und nicht 4.
Karl Käfer schrieb:> Wenn wir hier schon beim Korinthenkacken sind, dann bitte wenigstens> richtig: Fehler sollen nämlich nicht beseitigt werden, sondern Fehler> müssen beseitigt werden. Das unterscheidet sie von Warnungen, die nur> beseitigt werden sollen, aber nicht müssen.
Yo, das ist völlig richtig.
Zeno schrieb:> Jetzt wird mir was klar: Ich hätte an Stelle von 0x02 lieber 4 schreiben> sollen, dann hätte es vielleicht die Diskussion so gar nicht gegeben. Da> wir uns hier aber in einem Mikrocontrollerforum befinden, bin ich davon> ausgegangen, das das Umrechnen einer kleinen Hexzahl in eine Dezimalzahl> kein Problem darstellt.
Dir bereitet es offensichtlich Probleme, denn hexadezimal zwei ist exakt
das Gleiche wie dezimal zwei.
X zur Basis A ist stets das Gleiche wie X zur Basis B, sofern X eine
Ziffer ist die in beiden Zahlensystemen existiert.
Edit: Du Held! ;-)
Karl Käfer schrieb:> Michael S. schrieb:>> M. K. schrieb:>>> Ich sehe da nicht, dass ich schrieb man solle Fehler nicht beseitigen.>>> Hab vielleicht was auf der Brille.>>>> Wenn du>> also sagst, der Unterschied zwischen Fehlern und Warnungen ist, dass>> eine Warnung beseitigt werden soll, heißt es im Umkehrschluss, ein>> Fehler soll nicht beseitigt werden. Sonst wäre es kein Unterschied. Ich>> glaub aber auch, dass jeder weiß, dass du das so nicht gemeint hast,>> sondern nur sagen wolltest, dass Warnungen im allgemeinen beseitigt>> werden sollen, Fehler natürlich ebenso.>> Wenn wir hier schon beim Korinthenkacken sind, dann bitte wenigstens> richtig: Fehler sollen nämlich nicht beseitigt werden, sondern Fehler> müssen beseitigt werden. Das unterscheidet sie von Warnungen, die nur> beseitigt werden sollen, aber nicht müssen.
Ansich hatte ich auch nur versucht, mit anderen Worten zu erklären, was
(ich glaube) Rolf meinte. Auch wenn man wieder "streiten" könnte, ob
"müssen" auch "sollen" impliziert oder dass M.K.'s exaktes Zitat ist
"Ich sehe da nicht, dass ich schrieb man solle Fehler nicht
beseitigen." (es war also kein Wort von müssen), würde ich das Thema
gerne auf sich beruhen lassen. Jeder weiß, was gemeint ist, letztendlich
geht es nur um den Wortlaut. Ähnlich sinnvoll, wie sich bei einem
"for(;;;)" aufzuspielen, dass derjenige doch keine Ahnung hat, wie eine
for-Schleife geschrieben wird. Daher find ich es auch müßig so groß
darüber zu diskutieren. Ehrlich gesagt hab ich das schon abgehakt, weil
es gefühlt 300 Beiträge zurück liegt ;)
W.S. schrieb:> Michael S. schrieb:>>> It is good programming style to use the break, continue, and return statements>>> instead of the goto statement whenever possible.>> OK Michael, das war ein Zitat und nicht von dir, nun ja.>> Aber "whenever possible" ???>> Das ist ne Unverschämtheit.>> Da will mir ( MIR!! ) irgend jemand vorschreiben, was guter> Programmierstil ist. Und das soll sich darin ausdrücken, daß man alles> andere außer goto zu verwenden hat "whenever possible"? Dreistigkeit> sowas! Frechheit!
Ich kann und will auch garnicht urteilen, wann welcher Befehl Sinn
macht. Und ich würde auch nicht sagen, dass dir das jemand vorschreiben
will, sondern was eine Empfehlung seitens Microsoft ist. Es wird auch
empfohlen, Red-Bull nicht mit Alkohol zu mischen, doch es wird auch
niemandem verboten ;)
Daniel A. schrieb:> Ja, sollte man annehmen. Übrigens, 0x02 ist dezimal 2 und nicht 4.
Stimmt! Ich habe mich vertan - war irgendwie bei Byte. Aber trotz meines
Fehlers hast Du den Sinn Posts verstanden.
Mark B. schrieb:> Dir bereitet es offensichtlich Probleme, denn hexadezimal zwei ist exakt> das Gleiche wie dezimal zwei.
Schön für Dich das Du den Fehler gefunden hast - darfst ihn gern
behalten.
Schön für Dich, daß Du keine Fehler machst.
Es ging hier ums Prinzip und Daniel hat's offensichtlich erkannt.
Michael S. schrieb:> Es wird auch> empfohlen, Red-Bull nicht mit Alkohol zu mischen, doch es wird auch> niemandem verboten ;)
Goto verleiht Flügel!
;-)
Man kann damit aus einer Routine abzwitschern und damit Chaos
hinterlassen.
Schöner ist "Exit Do" oder "Exit For". Das gibt es in Bascom -und auch
noch andere Exite.
MfG Paul
Mitlesender schrieb:> Es ging hier ums Prinzip und Daniel hat's offensichtlich erkannt.
Das Prinzip ist, dass man magic numbers vermeidet. Schön wenn Du es
irgendwann erkennst.
Mitlesender schrieb:> Schön für Dich, daß Du keine Fehler machst.> Es ging hier ums Prinzip und Daniel hat's offensichtlich erkannt
Nö, ich hab mich nur auf das Zitierte bezogen und stimme der meinung des
damals Zitierten nicht zu. Meine Aussage war Sarkastisch zu verstehen
(wir brauchen in diesem Forum unbedingt Ironie und Sarkasmus tags...)
https://de.m.wikipedia.org/wiki/Sarkasmus
Mark B. schrieb:> Wir warten immer noch auf ein wirklich gutes Beispiel, welches diese> Aussage untermauert.https://www.kernel.org/doc/Documentation/CodingStyle
Chapter 7: Centralized exiting of functions
Ist m.M. nach ein gutes Beispiel fuer goto
Oder wenn du eine Sequenz hast, die schief gehen kann und aus mehreren
sequentiellen Schritten besteht (z.B. File oeffnen, File parsen, ...).
Dann "kann" goto uebersichtlicher sein als Gazillionen von Einrueckungen
und breaks und exits.
Fuer ein paar wenige Anwendungsfaelle ist mir ein goto lieber als all
die anderen verkrampften Sachen...
Michael S. schrieb:> Ich kann und will auch garnicht urteilen, wann welcher Befehl Sinn> macht.
Ich schon.
Aber daeum geht's bei dem Zitat auch garnicht. Hätte der Urheber
geschrieben, man möge mit goto sparsam umgehen und es nicht allzuhäufig
verwenden, weil es ja auch noch andere Sprachelemente in der
betreffenden Programmiersprache gibt, dann hätte ich ihm glatt
zugestimmt.
Aber es als "guten Programmierstil" zu predigen, daß man goto "whenever
possible" zu vermeiden habe, das ist der Moment, wo einem solchen
Prediger der nächstbeste Feudel um die Ohren gehört.
Leute, wir leben in einer Zeit, wo der Extremismus und Fanatismus
offensichtlich massiv im Kommen ist - ich kann davor nur warnen.
Bezogen auf die µC-Gefilde hat sich da was Ähnliches vor einigen Jahren
abgezeichnet durch das Auftauchen der Arm-Cortex und bei den
Programmiersprachen kam es schon 15 Jahre früher mit C. So ist es
verstehbar, daß der geistige Horizont bei gar Vielen mittlerweile arg
eingeschränkt ist und das ist ganz ganz schlecht. Auf lange Sicht
verblöden wir alle, wenn wir uns nicht um Vielfalt bemühen und
stattdessen die vorhandenen Ausdrucksmittel der wenigen noch vorhandenen
Programmiersprachen aus purem Mutwillen verteufelt werden.
Also: Kommt mal wieder runter von euren jeweiligen Bäumen. Unseren
Vorfahren hat es entwicklungsgeschichtlich gut getan, von den Bäumen zu
klettern und sich ein vielfältiges Menü zu gönnen anstelle immer nur
Banane zu essen.
W.S.
W.S. schrieb:> Aber es als "guten Programmierstil" zu predigen, daß man goto "whenever> possible" zu vermeiden habe
Ja, genau so ist es. Wann immer es eine bessere Möglichkeit als goto
gibt, verwendet man diese auch. Und somit benutzt man goto nur in
seltenen Ausnahmefällen.
Oder um es mit den Worten eines anderen auszudrücken:
"My take is that goto is fine, but only if it is adding value, never the
default choice."
berndl schrieb:> Oder wenn du eine Sequenz hast, die schief gehen kann und aus mehreren> sequentiellen Schritten besteht (z.B. File oeffnen, File parsen, ...).> Dann "kann" goto uebersichtlicher sein als Gazillionen von Einrueckungen> und breaks und exits.
Das alles muss aber nicht zwingend innerhalb ein und derselben Funktion
passieren. Und wenn ich die Schritte der Sequenz in einzelne Funktionen
aufteile, dann kann habe ich das Problem mit den Einrückungen und breaks
und exits sehr wahrscheinlich gar nicht mehr.
Viel Unbill lässt sich vermeiden, wenn man die Software-Design-Regel aus
dem sehr lesenswerten Buch "Clean Code" befolgt: One function does only
one thing.
W.S. schrieb:> ..., das ist der Moment, wo einem solchen> Prediger der nächstbeste Feudel um die Ohren gehört.>> Leute, wir leben in einer Zeit, wo der Extremismus und Fanatismus> offensichtlich massiv im Kommen ist - ich kann davor nur warnen.
Jawoll und muß auch mit dem "nächstbesten Feudel" unterdrückt werden.
Aber wen willst du vor wem warnen?
W.S. schrieb:> Michael S. schrieb:>> Ich kann und will auch garnicht urteilen, wann welcher Befehl Sinn>> macht.>> Ich schon.
Ich hab, wieso auch immer, nicht das geschrieben, was ich meine.
Natürlich weiß ich, wann welcher Befehl Sinn macht, sonst würde ja kein
Programm laufen. Ich meinte: Ich kann und will niemanden vorschreiben,
was er wie zu programmieren hat. Macht an der Stelle auch (mehr) Sinn.
W.S. schrieb:> Leute, wir leben in einer Zeit, wo der Extremismus und Fanatismus> offensichtlich massiv im Kommen ist - ich kann davor nur warnen.
Da geb ich dir zwar in gewisser Weise recht, aber es gibt gefühlt 5
Millionen andere Formen von Extremismus, die schlimmer sind und eher
beseitigt werden sollten, als der verwende-kein-goto-Extremismus ;)
Paul B. schrieb:> Ich mach' ein Selfie-Foto> Arm in Arm mit meinem GOTO> und schreib dazu noch einen Text> das nehm' ich mir fest FOR> demNEXT!Paul B. schrieb:> Es gibt durchaus auch Frauen,> die sich an GOTO trauen!
Reime-Monster ;)
Warum gibt es eigentlich für C so viele Abhandlungen darüber wie man
sauberen Code schreibt? Und warum gibt ebenso massenhaft Tools die dann
überprüfen ob man sich an Vorgaben gehalten? Und es werden immer mehr
solche Tools, zumindest bekommt man diesen Eindruck Jahr für Jahr auf
der Embedded.
Das Ganze muß ja wohl einen Grund haben, denn bei anderen
Programmiersprachen ist mir das so massiv noch nicht aufgefallen. Nur
das C so weit verbreitet ist kann da nicht der Grund sein. Ich befürchte
eher das bei C zu viele Schweinereien möglich sind, wo andere Compiler,
mit Recht, einem gehörig auf die Finger hauen.
Kann mir das mal einer erklären?
Zeno
Zeno schrieb:> Warum gibt es eigentlich für C so viele Abhandlungen darüber wie man> sauberen Code schreibt?
Gibts doch für C++ und Java auch. Da gibts IMO gefühlt keinen
Unterschied.
Zeno schrieb:> Nur> das C so weit verbreitet ist kann da nicht der Grund sein.
trägt aber mit Sicherheit nicht unwesentlich dazu bei
Zeno schrieb:> Ich befürchte> eher das bei C zu viele Schweinereien möglich sind
Das ist aber auch der Preis, den man für die, ich sag mal, Flexibilität
von C zahlen muss/darf.
Zeno schrieb:> Warum gibt es eigentlich für C so viele Abhandlungen darüber wie man> sauberen Code schreibt?> Nur das C so weit verbreitet ist kann da nicht der Grund sein.
Doch, das ist IMHO der Hauptgrund. Insbesondere bei sichheitskritischen
Steuerungsanwendungen (bspw. in der Auto- und Flugzeugindustrie) ist C
noch viel stärker präsent als anderswo, wo mittlerweile auch C++ und
Java weit verbreitet sind.
> Und warum gibt ebenso massenhaft Tools die dann überprüfen ob man sich> an Vorgaben gehalten?
In den genannten sichheitskritischen Bereichen sind solche Prüf-Tools
üblich und und oft sogar Pflicht.
Yalu X. schrieb:> Insbesondere bei sichheitskritischen> Steuerungsanwendungen (bspw. in der Auto- und Flugzeugindustrie) ist C> noch viel stärker präsent als anderswo,...
Ich glaube, es ist dann besser, nur noch Fahrrad zu fahren.
MfG Paul
Paul B. schrieb:> Ich glaube, es ist dann besser, nur noch Fahrrad zu fahren.
Nur zu! Ist ja auch viel gesünder und umweltschonender :)
Oder noch besser: GOTO Fuß :D
Im Hobbybereich kann jeder gerne programmiertechnisch tun und lassen,
was ihm oder ihr Spaß macht, aber in der Industrie schaut das sowieso
anders aus. Im sicherheitskritischen oder automotive Bereich gelten
strenge Standards, die verbindlich einzuhalten sind, z.B. MISRA-C:2012
und da lautet eine Regel knapp und klar: "Do not use goto." Nicht
zuletzt deshalb gilt diese Regel auch in meinen Vorlesungen und Übungen,
obwohl sie meine Studierenden auch immer wieder gerne wegdiskutieren
wollen...
In diesem Sinn: fröhliches Weiterdiskutieren. :)
Herby
Das GOTO bzw. das bedingte GOTO ist die Quintessenz der Ablaufsteuerung
seit Zuses Zeiten. Alles was danach an Schleifenkonstruktionen kam ist
menschliche Eitelkeit gepaart mit Bequemlichkeit.
@ Cube_S (Gast)
>Das GOTO bzw. das bedingte GOTO ist die Quintessenz der Ablaufsteuerung>seit Zuses Zeiten. Alles was danach an Schleifenkonstruktionen kam ist>menschliche Eitelkeit gepaart mit Bequemlichkeit.
Unsinn. Da kannst du ja gleich bei der Turingmaschine bleiben und
sämtliche höhere Abstraktion weglassen. VIEL SPAß!
Immer locker bleiben. Natürlich sind höhere Abstraktionen schön und
nützlich. Aber in ganz seltenen Fällen kann ein GOTO schon mal
ästhetischer sein als irgendwelche Hilfsvarieblen, die nur dazu da sind
das GOTO zu vermeiden. Wem die künstlerische Freiheit sagt es zu nutzen,
der soll es tun ohne über Tabus nachzudenken.
Cube_S schrieb:> Das GOTO bzw. das bedingte GOTO ist die Quintessenz der Ablaufsteuerung> seit Zuses Zeiten.
Nur so am Rande:
Die frühen Zuse-Rechner kannten noch keine Gotos und auch sonst keine
Sprungbefehle. Stattdessen konnte man eine sprungfreie Schleife¹
"programmieren", was auf heutigen Rechnern nicht mehr geht. Damals war
eben noch sauberes Programmieren angesagt ;-)
——————————
¹) Der der Begriff "Schleife" ist hier wörtlich zu nehmen.
GOTO macht in C bei einigen Fällen Sinn. Meistens kommen Anfänger mit
diesen Stellen aber nicht in Berührung. ;-)
Das ist ein Sprachmittel wie jedes andere auch und Du musst Dir
überlegen was in Deinem Anwendungsfall das Effektivste ist.
MCUA schrieb:>> Und wenn ich die Schritte der Sequenz in einzelne Funktionen aufteile..> einzelne Funktionen kosten in der Regel jedoch viel mehr CPU-Rechenzeit
Das mag vielleicht noch zutreffen, wenn man einen kleinen 8-Bit
Mikrocontroller mit wenigen Registern, wenig Hauptspeicher und niedriger
Taktfrequenz benutzt. Und diesen quasi schon "am Anschlag" betreibt.
Es gibt also sehr viele Projekte, in denen Mangel an Hardware-Ressourcen
schon lange kein Grund mehr ist, möglichst viel Code in eine Funktion zu
packen.
Dieser Code stammt aus der Atmel Studio 7.0 Hilfe. Zu finden unter
Getting started > Creating a project > Writing and Compiling Code.
Abgesehen davon, dass dieser Code fehlerhaft ist, ist er ausserdem ein
unfreiwilliges, aber treffendes Beispiel für einen unnötigen Einsatz von
goto. ;)
>> Ich glaube, es ist dann besser, nur noch Fahrrad zu fahren.Yalu X. schrieb:> Nur zu! Ist ja auch viel gesünder und umweltschonender :)>> Oder noch besser: GOTO Fuß :D
Ich glaube, daß ich mit meiner Aussage mindestens 2 Mann auf die C-hen
getreten bin.
Das ist mir aber ziemlich Brust.
;-)
MfG Paul
Falk B. schrieb:> @ Cube_S (Gast)>>>Das GOTO bzw. das bedingte GOTO ist die Quintessenz der Ablaufsteuerung>>seit Zuses Zeiten. Alles was danach an Schleifenkonstruktionen kam ist>>menschliche Eitelkeit gepaart mit Bequemlichkeit.>> Unsinn.
Eben kein Unsinn. Derjenige, der hier mal wieder mit haltlosen
Behauptungen um sich wirft, bist du.
Das GOTO bzw. eben das mit einer Bedingung versehene GOTO sind die
Fundamente jeglicher Programmierung. Ohne dieses könnte niemand
irgendeine Entscheidung in einem Programm treffen oder irgend eine
Schleife realisieren.
Daß es mittlerweile diverse Aufsätze auf dieses grundlegende GOTO gibt
(namens if..then, while.., repeat..until und wie sie alle heißen mögen),
ist eben nur Zuckerwerk obendrauf.
Dies solltest du mal begreifen, bevor du jemandem "Unsinn" an den Kopf
wirfst, der die Sache weitaus besser verstanden hat als du.
Solch hirnrissige Dogmatismen wie die hier diskutierte Verpönung von
GOTO findet sich in keiner anderen Sparte - oder hat schon mal jemand
von einer Verunglimpfung von GOTO oder anderen Sprachelementen in
Pascal- oder Delphi- oder Basic-Gefilden oder sonstwo gehört? Nee, alle
anderen machen nicht so einen Fanatismus auf - das findet sich eben nur
unter C-Jüngern.
Aber so langsam langweilt mich dieser Thread.
Augen-Tinnitus meinerseits?
Ich will ja nicht grob werden (obwohl das angemessen wäre).
Aber mir fällt da wieder ein alter Juwelierspruch ein, den mal jemand
aufgeweitet hatte und den ich hier nochmal aufweiten will:
"Frauen und Edelsteine (und C-Programmierer) haben eine Gemeinsamkeit:
Man erkennt ihren wahren Wert erst dann, wenn man sie mal aus der
Fassung gebracht hat." Und hier haben sich manche vorgeblichen
Hochkaräter als poplige Fälschungen erwiesen.
W.S.
W.S. schrieb:> oder hat schon mal jemand> von einer Verunglimpfung von GOTO oder anderen Sprachelementen in> Pascal- oder Delphi-
Ja, auch da gilt das selbe, im Falle von (Object-)Pascal eher sogar noch
stärker als bei C(++) da dort sowohl sprachlich als auch kulturell
bedingt die Meßlatte für sauberen Code nochmal gut zwei Meter höher
liegt als bei C oder C++.
> Im Netz wird da von gesprochen, das es verpöönt ist nichrr genutzt> werden soll.> Was nutz ihr bei solchen Sachen?> Paul
Wen interessiert, was im Netz steht. Wenn es für dich eine praktikable
Lösung ist, mach es halt.
@ W.S. (Gast)
>Eben kein Unsinn. Derjenige, der hier mal wieder mit haltlosen>Behauptungen um sich wirft, bist du.
Jaja . .
>Daß es mittlerweile diverse Aufsätze auf dieses grundlegende GOTO gibt>(namens if..then, while.., repeat..until und wie sie alle heißen mögen),>ist eben nur Zuckerwerk obendrauf.
Falsch. Es ist deutlich mehr als Zuckerwerk. Mit dem "Verbieten" des
klassischen Spaghetti-Goto hat man die Programmierung deutlich
verbessert.
>Dies solltest du mal begreifen, bevor du jemandem "Unsinn" an den Kopf>wirfst, der die Sache weitaus besser verstanden hat als du.
Der Papst?
>Solch hirnrissige Dogmatismen
Dogmen.
> wie die hier diskutierte Verpönung von>GOTO findet sich in keiner anderen Sparte - oder hat schon mal jemand>von einer Verunglimpfung von GOTO oder anderen Sprachelementen in>Pascal- oder Delphi- oder Basic-Gefilden oder sonstwo gehört?
Dort wird es genauso wenig benutzt und ist ebenso unnötig im normalen
Programmiereraltag wie in C.
>Aber so langsam langweilt mich dieser Thread.
Na dann geh woanders deine Weisheiten ablassen.
>Ich will ja nicht grob werden (obwohl das angemessen wäre).
Uhhhh, wir zittern schon ;-)
Herbert P. schrieb:> Im sicherheitskritischen oder automotive Bereich gelten> strenge Standards, die verbindlich einzuhalten sind, z.B. MISRA-C:2012> und da lautet eine Regel knapp und klar: "Do not use goto."
diese Behauptung zeigt einmal mehr, was für fanatisch religiöse Züge die
Debatte hat.
Erstens ist die Regel nicht klipp und klar (mandatory), noch nicht mal
„required”, sondern bloß advisory und zweitens folgt aus der Ergänzung
in MISRA-C 2012:
• The goto statement shall jump to a label declared later in the same
function.
• Any label referenced by a goto statement shall be declared in the same
block, or in any block enclosing the goto statement.
Das Gotos verwendet werden und verwendet werden dürfen.
Aber Hauptsache Du kannst in Deinen Vorlesungen und Übungen den
Soziopathen raushängen lassen.
Vlg
Timm
Paul B. schrieb:> Ich glaube, daß ich mit meiner Aussage mindestens 2 Mann auf die C-hen> getreten bin.
Mit Sicherheit!
Bernd K. schrieb:> Ja, auch da gilt das selbe, im Falle von (Object-)Pascal eher sogar noch> stärker als bei C(++) da dort sowohl sprachlich als auch kulturell> bedingt die Meßlatte für sauberen Code nochmal gut zwei Meter höher> liegt als bei C oder C++.
Das sehe ich genau so. Zwar wird auch in einschlägiger Literatur zu
Pascal geschrieben, daß man auf GOTO wenn möglich verzichten sollte,
aber es wird nicht verboten. Es gibt ja auch keinen Grund dafür. Wenn
man es sparsam und überlegt einsetzt, kann man dennoch gut lesbaren und
verständlichen Code schreiben.
Bei keiner anderen Programmiersprache wird so ein Geschrei um GOTO
gemacht wie bei C und insofern muß ich W.S. einfach recht geben, wenn er
schreibt:
W.S. schrieb:> Solch hirnrissige Dogmatismen wie die hier diskutierte Verpönung von> GOTO findet sich in keiner anderen SparteHerbert P. schrieb:> aber in der Industrie schaut das sowieso> anders aus. Im sicherheitskritischen oder automotive Bereich gelten> strenge Standards, die verbindlich einzuhalten sind, z.B. MISRA-C:2012> und da lautet eine Regel knapp und klar: "Do not use goto."
Natürlich gelten in der Industrie andere Maßstäbe als im privaten
Bereich und speziell im bei sicherheitsrelevanten Dingen ist es wichtig,
daß man Standards setzt. Ob es nun da Sinn macht GOTO zu verbieten
möchte ich bezweifeln. Ich glaube nicht, das ein Auto gegen einen Baum
fährt, bloß weil ein Programmierer GOTO benutzt hat. Die FW eines
Controllers im Auto schmiert dann eher wegen anderer Unzulänglichkeiten
in C ab, z.B. Speicherlecks, die es so massiv nur in C gibt. In keiner
anderen mir bekannten Programmiersprache ist es z.B. möglich über ein
Array hinaus zu schreiben. Genau dies ist ja auch eine oft genutzte
Möglichkeit um ein OS zu kompromitieren.
In C sind einfach zu viele Schweinereien möglich und genau deshalb gibt
es so unzählig viele Richtlinien und Codekontrolltools. Solche Dinge wie
zum Beispiel die for-Schleife ohne Argumente gibt es in anderen
Programmiersprachen nicht und das ist gut so.
Ich habe mir grad mal die Quellen von RTOS downgeloaded und dort nach
goto gesucht. Wie nicht anders zu erwarten, wurden 200 Dateien gefunden
wo goto benutzt wird und das nicht nur beim Errorhandling wie dieser
Auszug aus tcp.c zeigt:
Sind das jetzt alles Deppen? Nein diese Leute wissen ganz genau was sie
tun. RTOS ist im übrigen auch für Software im medizinischen Bereich
zertifiziert und dort sind die Anforderungen noch härter als in der
Automobilindustrie.
Zeno
Timm R. schrieb:> Erstens ist die Regel nicht klipp und klar (mandatory), noch nicht mal> „required”, sondern bloß advisory und zweitens folgt aus der Ergänzung> in MISRA-C 2012:
Ha da war mal einer der sich offenbar auskennt schneller als ich. Schön
das sich endlich mal Leute zu Wort melden die sich in
Industrierichtlinien offenbar gut auskennen und die eigentlich
unbegründeten Richtlinien schlichtweg widerlegen. Ich nehme mal an Timm
verdient seine Brötchen damit, denn sonnst könnte er nicht so detailiert
Auskunft geben - das ist schon Insiderwissen.
Zeno
Zeno schrieb:> Die FW eines> Controllers im Auto schmiert dann eher wegen anderer Unzulänglichkeiten> in C ab, z.B. Speicherlecks, die es so massiv nur in C gibt.
Speicherlecks liegen aber nie in der Sprache begründet sonderen sind
immer auf Unzulänglichkeiten des Programmieres zurück zu führen. Ein
beliebter, meiner Erfahrung nach, Anfängerfehler ist, dass man sich über
das Memory Management erst Gedanken macht wenn das Programm fertig ist,
da braucht man sich über Speicherlecks nicht wundern. Mit der Zeit, wenn
man schon ein paar mal damit auf die Schnautze gefallen ist, wird auch
das Memory Management besser.
Zeno schrieb:> Ich habe mir grad mal die Quellen von RTOS downgeloaded und dort nach
Wer "downgeloaded" schreibt, bei dem gehört auch "goto" zum
Sparchumfang.
W.S. schrieb:> Das GOTO bzw. eben das mit einer Bedingung versehene GOTO sind die> Fundamente jeglicher Programmierung.
Du ziehst einen unpassenden Maßstab für die Bewertung heran. Man
programmiert heutzutage üblicherweise nicht mehr in Assembler, sondern
in Hochsprachen ab der dritten Generation aufwärts. Somit ist Dein
Argument nicht wirklich eins. Was der Compiler oder der Interpreter aus
den üblichen Kontrollstrukturen macht, ist für den Programmierer im
Endeffekt irrelevant (abgesehen von Compilerfehlern, die aber selten
sind).
> Solch hirnrissige Dogmatismen wie die hier diskutierte Verpönung von> GOTO findet sich in keiner anderen Sparte - oder hat schon mal jemand> von einer Verunglimpfung von GOTO oder anderen Sprachelementen in> Pascal- oder Delphi- oder Basic-Gefilden oder sonstwo gehört?
Selbstverständlich. Oder dachtest Du, Edsger Dijkstra (Autor) und
Niklaus Wirth (Editor) haben sich speziell auf die Sprache C bezogen,
als sie den berühmten Artikel "Go To Statement Considered Harmful"
herausgaben?
Ich bleibe dabei: Wer heute noch goto verwendet, der macht sehr
wahrscheinlich einen Fehler in seinem Software-Design.
Die ohnehin schon wenigen Fälle, in denen goto als akzeptabel gilt,
beruhen meistens darauf dass zu viel Funktionalität in einer einzelnen
Funktion steckt. Wenn man sein Software-Design verbessert, treten diese
Konstellationen gar nicht mehr auf. Ergo gibt es dann auch keine
"Notwendigkeit" mehr für goto.
@ Zeno (Gast)
>aber es wird nicht verboten. Es gibt ja auch keinen Grund dafür. Wenn>man es sparsam und überlegt einsetzt, kann man dennoch gut lesbaren und>verständlichen Code schreiben.
Das ist doch relativ unstrittig.
>Auszug aus tcp.c zeigt:
AUA!
>Sind das jetzt alles Deppen?
Jain. Auch in diesem Beispiel ist goto reine Faulheit oder Schlamperei.
Man gewinnt weder Performance noch Lesbarkeit. Und das "Verbot" von goto
hat u.a. den Grund, das Codeanalysatoren für sauberen Code/MISRA etc.
damit deutlich mehr Probleme haben als mit sauberen Kontrollstrukturen!
Und vielleicht bin ich ja auch nur beschränkt, aber irgendwie muss man
bei dem Codeabschnitt ziemlich lange überlegen, WAS er bewirken soll und
WIE der Ablauf grob ist? Im Extremfall wird daraus eine Endlosschleife
;-)
>Nein diese Leute wissen ganz genau was sie>tun.
Wirklich?
> RTOS ist im übrigen auch für Software im medizinischen Bereich>zertifiziert
WELCHES RTOS?
> und dort sind die Anforderungen noch härter als in der>Automobilindustrie.
Auch dort gab es schon üble Fehler. Einer der bekanntesten ist der hier.
http://www.ccnr.org/fatal_dose.htmlhttps://en.wikipedia.org/wiki/Therac-25
Falk B. schrieb:> Das war jetzt echt schwer ohne goto . . .
Ehrlich gesagt finde ich die Variante mit goto in dem Fall etwas
übersichtlicher (!= besser).
Hallo,
ganz Deiner Meinung M. Köhler.
aus meiner persönlichen Sicht verfehlen die Goto-Verpöner an mehreren
Stellen das Argumentationsziel. Es ist nicht zu beweisen, dass man auf
das Goto verzichten k a n n, das ist trivial klar und völlig
unstrittig, sondern, dass man auf das Goto verzichten s o l l t e.
Und zwar nicht unter Berufung auf das göttliche Gebot
thou shalt not goto
sondern durch Aufzeigen der negativen Konsequenzen des verwendeten Goto.
Außerdem wird – in meiner Wahrnehmung – die i.d.R. triviale Tatsache
ignoriert, dass Code normalerweise sehr viel öfter gelesen wird, als
geschrieben.
Weiter oben haben wir das USB Beispiel:
1
caseGET_DESCRIPTOR:
2
if(bmRequestType==0x80)usb_get_descriptor();
3
elsegotounsupported_request;
4
break;
das goto springt nicht weit und es springt vorwärts. Durch die
Verwendung des Goto dokumentiert der Programmierer für jeden
Ahnungslosen sofort und ohne Nachdenken erkennbar, dass es keine andere
Variante geben kann, als GET_DESCRIPTOR mit bmRequestType == 0x80. Dafür
braucht der Leser weder Kenntnisse des USB Standards, noch sonst
irgendwelches Wissen. Der Code ist schnell zu überblicken, klar
strukturiert und logisch simpel. Mitternachtscode: Den versteht man auch
nach 10 Stunden am Bildschirm noch, selbst wenn der Kaffee alle ist und
ja, er ist, hinsichtlich der Anwendung des Goto, auch MISRA-C:2012
konform.
Die von den Verpönern vorgeschlagene Variante
1
if(bRequest==GET_DESCRIPTOR&&bmRequestType==0x80)
2
usb_get_descriptor();
hat auf der Pro-Seite, das Vermeiden von Goto. Allerdings werden in
diesem Fall auch bei einem nicht unterstützen Request noch 7 weitere
Bedingungen überprüft (mehr Code ausgeführt) und der Leser muss durch
Analyse von 8 Bedingungen herausfinden, dass sie exklusiv und frei von
Mehrfachnennungen sind.
Im Ergebnis wurde zwar ein religiöses Gebot befolgt, die Lesbarkeit aber
objektiv verschlechtert und die Ausführung verlangsamt.
Im RTOS Beispiel oben:
1
again:
2
if(port++>=TCP_LOCAL_PORT_RANGE_END){
3
port=TCP_LOCAL_PORT_RANGE_START;
4
}
haben wir eine Erhöhung der Anzahl der Lese-Zeilen von 7 auf 9 und eine
Erhöhung der Anzahl der Kontrollstrukturen von 4 auf 6. Zusätzlich haben
wir etwas, das ich persönlich, viel viel schlimmer finde, das aber
definitiv mindestens genau so verpönt ist: duplicate code. Drei mal
hintereinander die exakt identische Bedingung?
1
if(pcb->local_port==port)break;
2
}
3
if(pcb->local_port==port)break;
4
}
5
}while(pcb->local_port==port);
Ob der Compiler erkennt, dass der Fall, dass nur eine dieser Bedingungen
greift nie auftreten kann, vermag (und will) ich nicht einschätzen, das
hängt wahrscheinlich vom Optimierungslevel ab, der Leser muss das
jedenfalls auch erstmal kurz überprüfen. Das dauert keine zwei Sekunden,
aber vermutlich schaut man auch erstmal fünf mal hin, weil man sich gar
nicht vorstellen kann, dass jemand soetwas ohne perverse Hintergedanken
geschrieben haben könnte.
Im Resultat:
1 religiöses Gebot befolgt, Lesbarkeit verschlechtert, redundanten Code
reingebastelt und je nach Optimierung möglicherweise sogar mehr Code in
der Ausführung.
Bewiesen wurde nur, dass es auch ohne Goto g e h t, das ist aber gar
nicht die zu beurteilende Frage. Argumente, warum die komplexeren
Varianten b e s s e r sind, wurden nicht mal in homöopathischer
Dosierung gebracht, abgesehen eben vom fast schon satirischen
reiterieren der Regel oder Beleidigungen („Lernt doch mal Logik”).
Nur meine 2 Cent.
vlg
Timm
Timm R. schrieb:> sondern durch Aufzeigen der negativen Konsequenzen des verwendeten Goto.
Sieh es doch mal so herum: Warum verwendet jemand goto?
Vermutlich weil er ein ungünstiges Software-Design gewählt hat. Er
"repariert" damit quasi ein Problem - aber dieses Problem hätte er gar
nicht erst zu haben brauchen.
Wer vernünftiges Software-Design betreibt und sich an Regeln wie "One
function does only one thing" hält, der wird auch ohne goto auskommen.
Timm R. schrieb:> Die von den Verpönern vorgeschlagene Variante
Das beweist überhaupt gar nichts.
Wenn man richtig ernsthaft über solche Dinge diskutieren will, muss man
im Endeffekt bei den Requirements selbst anfangen. Nicht bei einer schon
existierenden Implementierung, die bereits beliebig viele Entscheidungen
des Programmierers und somit Einschränkungen enthält.
Wer einen halben Codeschnipsel als Ausgangspunkt wählt und dann steif
und fest behauptet: "Aber diese Code ist so besser mit goto!", der hat
das Problem nicht verstanden. Sehr wahrscheinlich war von vornherein die
Aufteilung des Codes in Funktionen schon nicht besonders clever
vorgenommen worden. Denn wenn sie es wäre, wäre dort zu 99,99999%
niemals ein goto aufgetaucht.
@ Timm Reinisch (Firma: privatfrickler.de) (treinisch)
>haben wir eine Erhöhung der Anzahl der Lese-Zeilen von 7 auf 9 und
Vollkommen egal.
>wir etwas, das ich persönlich, viel viel schlimmer finde, das aber>definitiv mindestens genau so verpönt ist: duplicate code. Drei mal>hintereinander die exakt identische Bedingung?
Ja, das ist sicher nicht optimal und kein Paradebeispiel. Aber manchmal
ist halt auch etwas Formalismus angesagt.
>jedenfalls auch erstmal kurz überprüfen. Das dauert keine zwei Sekunden,>aber vermutlich schaut man auch erstmal fünf mal hin, weil man sich gar>nicht vorstellen kann, dass jemand soetwas ohne perverse Hintergedanken>geschrieben haben könnte.
Hä? Das GEGENTEIL ist der Fall!! Man sieht, daß alle drei Schleifen nach
dem gleichen suchen, nämlich
pcb->local_port == port
So lange läuft die Suche.
>1 religiöses Gebot befolgt,
Es ist keine Religion, sondern ein Konzept. Schau dir mal echte
Religionen und deren "Gedankenwelt" aka Brimborium an, besonders die,
welche gern und oft Schlagzeilen macht (jaja OT).
> Lesbarkeit verschlechtert,
Keine Sekunde.
> redundanten Code reingebastelt
Nö, es ist halt 3x die gleiche Bedingung.
> und je nach Optimierung möglicherweise sogar mehr Code in>der Ausführung.
Stimmt, aber da ist hier nicht entscheidend.
>nicht die zu beurteilende Frage. Argumente, warum die komplexeren
Komplex?
>Varianten b e s s e r sind, wurden nicht mal in homöopathischer>Dosierung gebracht,
Kannst du lesen?
"Und das "Verbot" von goto
hat u.a. den Grund, das Codeanalysatoren für sauberen Code/MISRA etc.
damit deutlich mehr Probleme haben als mit sauberen Kontrollstrukturen!"
Wehret den Anfängen. Wenn einmal goto OK ist, wird es das irgendwann
immer mehr. Und dann haben wir wieder den (Spaghtetti-)Salat.
> Solch hirnrissige Dogmatismen wie die hier diskutierte Verpönung von> GOTO findet sich in keiner anderen Sparte
Doch das gibts überall.
sogenannte Codeanalysatoren sollten kein Problem damit haben, "gültige"
von "ungültigen" goto's zu unterscheiden (bsp.weise nur innerhalb eine
Funkt. und nur vorwärts)
M. K. schrieb:> Speicherlecks liegen aber nie in der Sprache begründet sonderen sind> immer auf Unzulänglichkeiten des Programmieres zurück zu führen.
JAEIN! Erst mal sind sie in der Sprache begründet, weil diese zu läßt,
das man über Arraygrenzen hinaus schreiben kann. Und erst dann kommt der
Programmierer, der auch nur ein Mensch ist und wie wir alle halt mal
Fehler macht. Einfaches Beispiel Stringverarbeitung, eine Sache die C
nicht wirklich kann. Du deklarierst ein Zeichenarray mit 10 Zeichen
Länge und dann schreibst Du irgendwann mal einen String rein der 11
Zeichen lang ist und schon ist es passiert. Eigentlich darfst Du ja nur
9 Zeichen reinschreiben, weil das letzte Zeichen das berühmte 0 Byte
ist, auch so eine Krücke, damit C das Stringende erkennt. Schreibst Du
10 Zeichen rein passiert erst mal nichts aber Du merkst es wenn Du den
String wieder auslesen möchtest. Nicht nur das es keine Strings in C
gibt, eben nur diese Zeichenarrays, kann C zu allem Überfluss noch nicht
mal richtig mit Arrays umgehen und Du mußt ihm sagen wie lang Dein Array
ist. Das sind Basics. Selbst so alte Programmiersprachen wie FORTRAN
können das.
nichtCler schrieb:> Wer "downgeloaded" schreibt, bei dem gehört auch "goto" zum> Sparchumfang.
Stimmt! Bei Dir gehört es definitiv nicht zum "Sparchumfang" - Du kannst
noch nicht einmal richtig deutsch. Wer im Glashaus sitzt sollte lieber
nicht mit Steinen werfen.
Falk B. schrieb:> Jain. Auch in diesem Beispiel ist goto reine Faulheit oder Schlamperei.> Man gewinnt weder Performance noch Lesbarkeit ...
Ohne Dir jetzt zu nahe treten zu wollen, aber der zitierte Satz spricht
schon für eine gewisse Arroganz bzw. Ignoranz.
Falk B. schrieb:> Und vielleicht bin ich ja auch nur beschränkt, aber irgendwie muss man> bei dem Codeabschnitt ziemlich lange überlegen, WAS er bewirken soll und> WIE der Ablauf grob ist? Im Extremfall wird daraus eine Endlosschleife> ;-)
Du kannst Dir ja die Quellen von www.freertos.org selbst mal anschauen,
dann wird sich Dir der Codeschnipsel bestimmt erschließen. Speziell die
von mir zitierte Quelldatei dürfte für einen Erfahrungsträger wie Dich
kein Problem darstellen. Ich habe sie rein zufällig gewählt, es hätte
auch eine andere treffen können, die ein goto-Befehl enthält. Ich wollte
den Auszug nicht zu lang machen. Mir ging es nur um die Verwendung des
goto.
Falk B. schrieb:>> RTOS ist im übrigen auch für Software im medizinischen Bereich>>zertifiziert>> WELCHES RTOS?
Genau das von mir zitierte.
Falk B. schrieb:> Auch dort gab es schon üble Fehler. Einer der bekanntesten
Es gibt keine fehlerfreie Software! Da kannst Du noch so viele
Codeanalyzer einsetzen wie Du möchtest, denn auch die sind nur von
Menschen gemacht.
Timm R. schrieb:> das goto springt nicht weit und es springt vorwärts. Durch die> Verwendung des Goto dokumentiert der Programmierer für jeden> Ahnungslosen sofort und ohne Nachdenken erkennbar ....
Endlich mal einer der sachlich bleibt und die Sache nüchtern analysiert.
>>>> Chapeau! <<<<Timm R. schrieb:> hat auf der Pro-Seite, das Vermeiden von Goto. Allerdings werden in> diesem Fall auch bei einem nicht unterstützen Request noch 7 weitere> Bedingungen überprüft (mehr Code ausgeführt)
Der Bursche gefällt mir immer besser!
@Timm: Schau Dir nur mal die unmittelbar Deinem Post folgenden Posts an.
Schlimm oder? Man will sich einfach nichts sagen lassen und beharrt stur
und rechthaberich auf seinen Dogmen : "Wir vermeiden GOTO um jeden Preis
koste es Codezeilen und Ressourcen was es wolle." Na gut gut geht eben
auch so.
Mark B. schrieb:> Wer einen halben Codeschnipsel als Ausgangspunkt wählt und dann steif> und fest behauptet: "Aber diese Code ist so besser mit goto!", der hat> das Problem nicht verstanden.
Du darfst Dir gern den kompletten Quelltext ansehen - die Quellen hatte
ich ja genannt - und es dann besser machen. Vielleicht solltest Du aber
auch mit RTOS-Entwicklern in Kontakt treten und ihnen zeigen, wie man es
richtig macht. Sollte für Dich doch kein Problem sein, denn wenn man
Deinen, von mir zitierten, Post weiter liest, wird einem doch sehr
schnell klar, daß Du schon lange erkannt hast wo es krankt. Die
RTOS-Entwickler sind Dir bestimmt dankbar, wenn Du ihnen auf Sprünge
hilfst.
MCUA schrieb:> sogenannte Codeanalysatoren sollten kein Problem damit haben
Werden sie aber haben, da sie unter den gleichen Dogmen geschrieben
wurden wie sie hier diskutiert werden
Zeno
Falk B. schrieb:
...
> for (i = 0; i < NUM_TCP_PCB_LISTS; i++) {> for(pcb = *tcp_pcb_lists[i]; pcb != NULL; pcb = pcb->next) {> if (pcb->local_port == port) break;> }
...
>> Das war jetzt echt schwer ohne goto . . .
Na offenbar schon, im goto fall wird dort wieder nach oben gesprungen,
du verlässt statdessen die Schleife. Ein continue wäre hier angesagt,
oder besser ein goto ;)
Zeno schrieb:> JAEIN! Erst mal sind sie in der Sprache begründet, weil diese zu läßt,> das man über Arraygrenzen hinaus schreiben kann. Und erst dann kommt der> Programmierer, der auch nur ein Mensch ist und wie wir alle halt mal> Fehler macht. Einfaches Beispiel Stringverarbeitung, eine Sache die C> nicht wirklich kann. Du deklarierst ein Zeichenarray mit 10 Zeichen> Länge und dann schreibst Du irgendwann mal einen String rein der 11> Zeichen lang ist und schon ist es passiert. Eigentlich darfst Du ja nur> 9 Zeichen reinschreiben, weil das letzte Zeichen das berühmte 0 Byte> ist, auch so eine Krücke, damit C das Stringende erkennt. Schreibst Du> 10 Zeichen rein passiert erst mal nichts aber Du merkst es wenn Du den> String wieder auslesen möchtest. Nicht nur das es keine Strings in C> gibt, eben nur diese Zeichenarrays, kann C zu allem Überfluss noch nicht> mal richtig mit Arrays umgehen und Du mußt ihm sagen wie lang Dein Array> ist. Das sind Basics. Selbst so alte Programmiersprachen wie FORTRAN> können das.
Naja, du hast damit zum großen Teil sicherlich recht. Man muss aber auch
sagen: Der Programmierer weiß ja um diese Schwäche, es obliegt also ihm
sich um das Speicher-Management zu kümmern. Beispeil Strings: Ich weiß,
dass ich in ein Array schreibe und ich weiß, dass das 0-Byte am Ende
stehen muss. Ich kann doch also vorher schaun ob der String, den ich in
ein Array schreiben will, auch da rein passt. Man muss sich halt drum
kümmern oder man vertraut darauf, dass der String nie länger sein wird
als das Zielarray wo er rein soll.
Alternativ wird man von niemanden daran gehindert sich Funktionen zu
überlegen die einem das Leben mit dem Speichermanagement erleichtern.
Möglicherweise gibt es auch schon welche die man nutzen kann.
@ Zeno (Gast)
>> Jain. Auch in diesem Beispiel ist goto reine Faulheit oder Schlamperei.>> Man gewinnt weder Performance noch Lesbarkeit ...>Ohne Dir jetzt zu nahe treten zu wollen, aber der zitierte Satz spricht>schon für eine gewisse Arroganz bzw. Ignoranz.
Ein hohes Niveau sieht nur von unten wie Arroganz aus ;-)
>> Auch dort gab es schon üble Fehler. Einer der bekanntesten>Es gibt keine fehlerfreie Software! Da kannst Du noch so viele>Codeanalyzer einsetzen wie Du möchtest, denn auch die sind nur von>Menschen gemacht.
Schwarz-Weiß Denken. Es geht nicht um perfekte, fehlerfreie Software,
sondern um um die Vermeidung bekannter Fehlerquellen und Konzepte!
@Daniel Abrecht (daniel-a)
>> for (i = 0; i < NUM_TCP_PCB_LISTS; i++) {>> for(pcb = *tcp_pcb_lists[i]; pcb != NULL; pcb = pcb->next) {>> if (pcb->local_port == port) break;>> }>Na offenbar schon, im goto fall wird dort wieder nach oben gesprungen,>du verlässt statdessen die Schleife. Ein continue wäre hier angesagt,>oder besser ein goto ;)
Über diese Aussage solltest du noch einmal nachdenken . . .
Zeno schrieb:> Du darfst Dir gern den kompletten Quelltext ansehen
Klar, weil das ja auch sinnvoll ist. NICHT.
> - die Quellen hatte> ich ja genannt - und es dann besser machen. Vielleicht solltest Du aber> auch mit RTOS-Entwicklern in Kontakt treten und ihnen zeigen, wie man es> richtig macht.
Deine Argumentation ist eine einzige "logical fallacy". Nur weil Code
mit goto sich in einem Projekt wie RTOS befindet, kann man daraus nicht
schließen dass die Verwendung von goto gut und richtig und sinnvoll ist.
Wer Ahnung von Softwareentwicklung hat, der weiß dass auch Code von
schlechter Qualität funktionieren kann. Er kann sogar gut funktionieren,
in dem Sinne dass er die Anforderungen vollständig erfüllt. Er kann aber
unnötig schlecht zu lesen, zu warten, zu erweitern sein.
"Code erfüllt Anforderungen" und "Code ist von einer guten Qualität"
sind mithin also zwei vollkommen verschiedene Dinge.
Ich weiß nicht nach welchen Programmierrichtlinien RTOS entwickelt wird.
Oder nach welchen Maßstäben die ihre Qualität prüfen. Tun sie das? Ich
hoffe doch. Aber wir wissen alle, wieviel Budget im durchschnittlichen
Software-Projekt für die Qualitätssicherung ausgegeben wird - das kann
auch schon mal gerne gegen Null gehen.
Ich habe in meinem Programmiererleben Hunderttausende Zeilen von Code
gesehen, und vieles davon war ziemliche Grütze die man so nicht nochmal
schreiben würde wenn man es neu machen würde. Die Qualität von Code ist
in vielen Projekten nahezu beliebig. Also auch beliebig schlecht.
Wer goto verteidigt, der hat wahrscheinlich nie in seinem Leben ein
gutes Buch zum Thema Software-Design gelesen und verstanden. Und der
schreibt wahrscheinlich auch Funktionen, die oft und gerne über mehrere
Bildschirmseiten hinweg gehen - und denkt sich nichts dabei.
Es ist niemandem verboten, mal ein gutes Buch zum Thema Software-Design
zu studieren. Aber nein, das wäre ja zu anstrengend, und man müsste
vielleicht seine Gewohnheiten beim Programmieren ändern. Das darf
natürlich nicht sein. Man könnte am Ende noch ein richtig guter
Entwickler werden. Gott bewahre!
Wer Ironie findet, darf sie behalten. ;-)
Falk B. schrieb:> Ein continue wäre hier angesagt,>>oder besser ein goto ;)>> Über diese Aussage solltest du noch einmal nachdenken . . .
Ups, bei verschachtelten schleifen und break/continue übersehe ich immer
ein paar schleifen... Schade, dass es in c nicht wie in JavaScript und
Java labeled blocks gibt.
Zeno schrieb:> nichtCler schrieb:>> Wer "downgeloaded" schreibt, bei dem gehört auch "goto" zum>> Sparchumfang.> Stimmt! Bei Dir gehört es definitiv nicht zum "Sparchumfang" - Du kannst> noch nicht einmal richtig deutsch. Wer im Glashaus sitzt sollte lieber> nicht mit Steinen werfen.
Ja, das ist wirklich peinlich für mich, sehe meinen Tippfehler ein und
würde ihn gerne ungeschehen machen. Aber was ist nur mit dem
"downgeloaded"? War das ein Tippfehler, ein Rechtschreibfehler oder ist
das ein noch zu verpönender neuer Wotschöpfungversuch?
M. K. schrieb:> Der Programmierer weiß ja um diese Schwäche
Ja und genau das ist der Knackpunkt, es ist vom Programmierer abhängig
und nicht von der Sprache/Compiler und der macht nun mal Fehler.
Mark B. schrieb:> Deine Argumentation ist eine einzige "logical fallacy". Nur weil Code> mit goto sich in einem Projekt wie RTOS befindet, kann man daraus nicht> schließen dass die Verwendung von goto gut und richtig und sinnvoll ist.
Schlimm jetzt haben wir schon den 2. Fall wo Programmierer bei einem
umfänglichen Projekt schwerwiegende Fehler machen.
So langsam kristallisiert sich hier heraus, das nur 2 (eingewisser M.B.
und F.B) gibt die alles korrekt machen. Ich kann's nur noch mal
wiederholen: Wie überheblich.
nichtCler schrieb:> War das ein Tippfehler, ein Rechtschreibfehler oder ist> das ein noch zu verpönender neuer Wotschöpfungversuch?
Naja ist wohl eher ein "Wotschöpfungsversuch" im derzeit allgemein
üblichen Denglisch. Hätte vielleicht eher "heruntergeladen" schreiben
sollen.
Aber sei weiter vorsichtig mit Steine werfen, denn das Echo könnte
furchtbar sein.
Zeno
@nichtCler
Bevor Du wieder meckerst, ja ich habe einen Fehler gemacht und ein
Leerzeichen vergessen.
Zeno schrieb:> eingewisser
Korrektur: ein gewisser
Zeno schrieb:> Ja und genau das ist der Knackpunkt, es ist vom Programmierer abhängig> und nicht von der Sprache/Compiler und der macht nun mal Fehler.
Sag ich ja: Der Programmierer macht den Fehler, nicht die Sprache. Die
hilft ihm schlimmsten Falls nur nicht den Fehler erst gar nicht zu
machen ;)
Zeno schrieb:> So langsam kristallisiert sich hier heraus, das nur 2 (eingewisser M.B.> und F.B) gibt die alles korrekt machen. Ich kann's nur noch mal> wiederholen: Wie überheblich.
Moment, jetzt bin ich verwirrt wer für und wer gegen goto ist. Hab ich
das so noch richtig im Kopf:
Ich bin dafür, sofern es den Code vereinfacht, lesbarer macht und nicht
zu oft verwendet wird.
Falk Brunner ist dagegen, sofern es nicht sinvoll oder notwendig ist?
Mark Brandis ist dagegen, wenn immer es ohne geht oder es von einem
Anfänger benutzt wird?
W.S. scheint für goto zu sein?
Zeno sympathisiert mit W.S. ?
Habe ich das so richtig im Kopf?
Zeno schrieb:> Naja ist wohl eher ein "Wotschöpfungsversuch" im derzeit allgemein> üblichen Denglisch. Hätte vielleicht eher "heruntergeladen" schreiben> sollen.
Danke.
> ..., denn das Echo könnte furchtbar sein.
Noch furchtbarer als meine Kommentare? Das macht mir Angst und stelle
deshalb das Schreiben in diesem thread ein.
Mark B. schrieb:> Wer goto verteidigt, der hat wahrscheinlich nie in seinem Leben ein> gutes Buch zum Thema Software-Design gelesen und verstanden.
Ich glaube nicht, dass ein Buch lesen reicht. Zuerst muss man erkennen,
welche Probleme "goto" verursacht. Wenn man nur eigenen Code schreibt
und liest, womöglich außer C-ähnlichen Sprachen nie etwas anderes
gelernt hat, entwickelt man kein Gespür für die Problem-Ecken. Man
bleibt auf einem mental niedrigem Niveau hängen.
Hier wurden im wesentlichen zwei "goto"-Konstrukte vorgestellt, wenn
auch im Zweiten nichteinmal das Wort "goto" vorkommt:
1
switch(x)
2
{
3
caseA:
4
if(something)
5
action();
6
else
7
gotolabel;
8
break;
9
10
...
11
}
1
switch(x)
2
{
3
caseA:
4
if(something)
5
break;
6
return;
7
8
...
9
}
Beide Konstrukte sind schlimm. Keine strukturierte Programmierung
vorhanden. Im Prinzip ist das "switch" nur unnötiges Beiwerk. Der ganze
Programmablauf beruht komplett auf verschachtelte Sprünge.
Solche Dinge kann man in Foren den Menschen nicht beibringen. Dazu
benötigt man geduldige Gespräche in denen man den Programmierer zum
Nachdenken anregt.
Im Prinzip ist es einfach: Wer "goto" verteidigt und nicht missbilligt,
muss noch ein paar Sprossen die Leiter der Erkenntnis nach oben
klettern. So wie sich jedes kleine Kind mal die Pfoten an einer heißen
Herdplatte verbrennen muss, um zu erkennen, dass ein "Achtung,
gefährlich" der Eltern ernst zu nehmen ist, müssen Programmierer mit
Goto-Konstrukte sich erst eine blutige Nase holen, z.B. weil man im
Flieger zum Kunde sitzt, weil ein dummer, vermeidbarer Software-Fehler
in einer Zeile ein System stillsetzt. So spätestens beim zweiten mal
sollte man es kapiert haben.
Zeno schrieb:> Ja und genau das ist der Knackpunkt, es ist vom Programmierer abhängig> und nicht von der Sprache/Compiler und der macht nun mal Fehler.
Nein, das ist zu einfach.
Ein Stecker für eine DC-Gleichspannung ist in verpolungssicherer
Ausführung deutlich besser, als einer auf dem die Polung nur aufgedruckt
ist und dennoch falsch zusammengesteckt werden kann.
So ist es auch mit "C" und seinem "goto". Das ist ein Stecker der nicht
Verpolungssicher ist. Es lohnt sich, den nicht einzusetzen.
Programmierer schrieb:> Nein, das ist zu einfach.
Warum soll das zu einfach sein?
Programmierer schrieb:> Ein Stecker für eine DC-Gleichspannung ist in verpolungssicherer> Ausführung deutlich besser, als einer auf dem die Polung nur aufgedruckt> ist und dennoch falsch zusammengesteckt werden kann.
Na sicher ist es besser, wenn man den Spass so baut, dass Fehler nicht
möglich sind, keine Frage. Aber, um hier zum Thema zurück zu kommen: Man
kann auch while-Schleifen und Co prima falsch zusammenstricken und sich
wundern warum das Programm nicht funktioniert. Und in Fortran und Co
geht das auch prima da Endlosschleifen zu generieren.
@ Programmierer (Gast)
>So ist es auch mit "C" und seinem "goto". Das ist ein Stecker der nicht>Verpolungssicher ist. Es lohnt sich, den nicht einzusetzen.
Ein sehr schönes Beispiel! Das ist Karl Heinz Buchegger würdig!
Herbert P. schrieb:> Nicht zuletzt deshalb gilt diese Regel auch in meinen Vorlesungen> und Übungen, obwohl sie meine Studierenden auch immer wieder gerne> wegdiskutieren wollen...
Was habe ich diese auf Formalien herum reitenden Professoren während
meines Studiums gehasst. Meistens waren das auch genau die, bei denen
ich am wenigsten gelernt habe, da sie aus ihrer fachlichen "Ecke" nicht
heraus kamen. Aber egal.
Ich hätte aber einen Vorschlag für dich: Wenn du so davon überzeugt bist
das die Verwendung von goto absolut abzulehnen ist, lasse doch von
deinen Studenten einfach mal ein nicht triviales Programm schreiben in
dem ausschließlich goto erlaubt ist. Ich finde mit einen solchen
Beispiel könnte man doch sicherlich sehr anschaulich zeigen was für oder
gegen die Verwendung von goto spricht.
rhf
Falk B. schrieb:> @ Programmierer (Gast)>>>So ist es auch mit "C" und seinem "goto". Das ist ein Stecker der nicht>>Verpolungssicher ist. Es lohnt sich, den nicht einzusetzen.>> Ein sehr schönes Beispiel! Das ist Karl Heinz Buchegger würdig!
Naja, wenn ich schreibe
1
while(myVar<10){
2
myVar=1;
3
}
ums mal ganz einfach zu halten bin ich da auch nicht wirklich
"verpolungssicher". Und das gilt auch für andere Schleifen und Co.
Durchs Knie ins Auge schießen kann man in C nicht nur mit goto, das geht
mit allen Schleifen prima.
Programmierer schrieb:> Im Prinzip ist es einfach: Wer "goto" verteidigt und nicht missbilligt,> muss noch ein paar Sprossen die Leiter der Erkenntnis nach oben> klettern
Wie du in deinem Beitrag selbst schon schreibst ist es wichtig gut
strukturierte Software zu schreiben und du zeigst ja auch das man ohne
goto einiges falsch machen kann. Goto kann falsch angewendet, schnell zu
schlecht strukturierter Code führen aber in einigen Fällen auch sehr
hilfreich sein um gut strukturierten Code zu erzeugen.
sepp schrieb:> Goto kann falsch angewendet, schnell zu schlecht strukturierter Code> führen aber in einigen Fällen auch sehr hilfreich sein um gut> strukturierten Code zu erzeugen.
Ich gebe einen Kasten Bier aus, sobald es jemandem gelingt diese
Behauptung zu beweisen.
Die bisherigen Beispiele sind kein Beweis, denn sie sind entweder
unvollständig oder verstoßen gegen Best Practice-Regeln des Software
Designs oder beides.
Mark B. schrieb:> Die bisherigen Beispiele sind kein Beweis, denn sie sind entweder> unvollständig oder verstoßen gegen Best Practice-Regeln des Software> Designs oder beides.
Diese Aussage ist reines Blabla.
Goto wird erfolgreich in gut strukturiertem Code angewendet. Dazu gibt
es genug Beispiel, auch wenn du sie mit dieser Pauschalaussage abweist.
Punkt.
blablablubb schrieb:> Goto wird erfolgreich in gut strukturiertem Code angewendet.
Das ist eine Aussage. Aussagen können wahr oder falsch sein. Oder auch
teilweise wahr. Eine Aussage zu tätigen macht sie alleine noch nicht
wahr.
> Dazu gibt es genug Beispiel, auch wenn du sie mit dieser Pauschalaussage> abweist.
Dann zeig mir eins. Ein Beispiel mit goto, wo man keine andere
Unterteilung des Codes in Funktionen, kein anderes Software Design hätte
wählen können, das besser gewesen wäre.
Die bisher gezeigten Beispiele kann man alle einem Refactoring
unterziehen, die den Code besser machen. Den gleichen Code in mehrere
kleinere Funktionen aufzuteilen macht ihn besser verständlich, und er
vereinfacht ebenso die Unit Tests. Letztere machen viele Programmierer
gar nicht erst - ich weiß. Damit geben sie aber von vornherein zu
Protokoll, dass sie es mit der Softwarequalität eh nicht so genau
nehmen. Und solchen Leute soll ich vertrauen, wenn sie sagen dass goto
gut sei?
>Ich gebe einen Kasten Bier aus, sobald es jemandem gelingt diese>Behauptung zu beweisen.
wie schon geschrieben
Wenn bsp.weise in mehreren Else-Zweigen die Gleiche (Fehler oder
Sonstige)Behandlung durchgeführt werden soll.
Das geht Nicht ohne Umwege!
MCUA schrieb:> wie schon geschrieben> Wenn bsp.weise in mehreren Else-Zweigen die Gleiche (Fehler oder> Sonstige)Behandlung durchgeführt werden soll.> Das geht Nicht ohne Umwege!
Dann hat man einen Fehler bzw. eine Schwachstelle im Software-Design:
Eine Funktion, die mehrere Dinge tut anstatt nur eines.
Der Thread wird lang und länger...
Hier mal Wikipedia als interessante Quelle (hatten wir noch nicht,
oder?): https://en.wikipedia.org/wiki/Goto#Common_usage_pa...
In den Referenzen findet man dann auch u.a. Linus' Statement dazu:
I think goto's are fine, and they are often more readable than large
amounts of indentation. That's especially true if the code flow isn't
actually naturally indented (in this case it is, so I don't think using
goto is in any way clearer than not, but in general goto's can be
quite good for readability).
Und dann weiter, in seiner gewohnt netten Art: ;-)
Of course, in stupid languages like Pascal, where labels cannot be
descriptive, goto's can be bad. But that's not the fault of the goto,
that's the braindamage of the language designer.
Mikro 7. schrieb:> In den Referenzen findet man dann auch u.a. Linus' Statement dazu
Linus Torvalds hat nie ein Buch über Software-Design geschrieben. Oder
über Software-Architektur. Oder darüber, wie man Software richtig
testet. Oder darüber, wie man Software so entwickelt dass man eine
bestimmte Qualität sicherstellen kann.
Warum wohl? ;-)
Falk B. schrieb:> do {> if (port++ >= TCP_LOCAL_PORT_RANGE_END) {> port = TCP_LOCAL_PORT_RANGE_START;> }> /* Check all PCB lists. */> for (i = 0; i < NUM_TCP_PCB_LISTS; i++) {> for(pcb = *tcp_pcb_lists[i]; pcb != NULL; pcb = pcb->next) {> if (pcb->local_port == port) break;> }> if (pcb->local_port == port) break;> }> } while (pcb->local_port == port);>> return port;> }
obwohl ich in den letzten Jahren nur in einem Fall, dafür gleich
mehrmals goto verwendet habe, nämlich als ich ein Fortranprogramm 1:1 in
C umgeschrieben habe weil ich die ganzen verschachtelten gotos nicht
mehr überblickt habe, muss ich leider sagen dass diese Umsetzung
fehlerhaft ist:
wenn die innerste Schleife mit
pcb == NULL
abbricht und dann zu
if (pcb->local_port == port)
kommt gibt es einen Fehler. Richtig wäre stattdessen
if ( pcb!=NULL )
entsprechend beim while
i < NUM_TCP_PCB_LISTS
hier Mal meine Version des obigen Codes (Tippfehler incl.)
das while (1) zeigt gut dass hier eine Endlosschleife droht
int portIsInList( PCB *pcb, PORT port )
{
for( ; pcb != NULL; pcb = pcb->next)
if (pcb->local_port == port)
return true;
return false;
}
while ( 1 )
{
if (port++ >= TCP_LOCAL_PORT_RANGE_END) {
port = TCP_LOCAL_PORT_RANGE_START;
}
/* Check all PCB lists. */
for (i = 0; i < NUM_TCP_PCB_LISTS; i++)
if ( portIsInList(*tcp_pcb_lists[i], port)
break;
if ( i == NUM_TCP_PCB_LISTS )
return port;
}
>> wie schon geschrieben>> Wenn bsp.weise in mehreren Else-Zweigen die Gleiche (Fehler oder>> Sonstige)Behandlung durchgeführt werden soll.>> Das geht Nicht ohne Umwege!>Dann hat man einen Fehler bzw. eine Schwachstelle im Software-Design:
Oder dein Design ist zu billig.
Man kann nämlich nicht ausschliessen, dass im Programm mehrere
Überprüfungen (betr. eines Sachverhalts) gemacht werden sollen, die im
Nicht-Erfolgs-Falle in einer gemeinsamen Behandlung münden.
@ Walter S. (avatar)
>mehr überblickt habe, muss ich leider sagen dass diese Umsetzung>fehlerhaft ist:>wenn die innerste Schleife mit>pcb == NULL>abbricht und dann zu>if (pcb->local_port == port)>kommt gibt es einen Fehler.
Hmm, stimmt.
> Richtig wäre stattdessen>if ( pcb!=NULL )>entsprechend beim while>i < NUM_TCP_PCB_LISTS
Hmm.
>hier Mal meine Version des obigen Codes (Tippfehler incl.)>das while (1) zeigt gut dass hier eine Endlosschleife droht
Auch die ist nicht korrekt ;-)
Und ich mag keine Schleifen mit nur einer Anweisung ohne Klammern.
> if ( i == NUM_TCP_PCB_LISTS )> return port;> }
Und welchen Rückgabewert gibt es, wenn die Bedingung NICHT erfüllt ist?
Aber der Ansatz mit dem Zerlegen in Teilfunktionen ist deutlich besser!
Genau SO macht man das!
Aber ich muß gestehen, daß ich den Sinn dieses Programmabschnitts noch
nicht so ganz verstehe.
Es gibt ein Array pcb, welches Pointer auf verkettete Listen enthält
(äußere Schleife). In der inneren Scheilfe wird nach einem Eintrag
gesucht, welcher == port ist. Ist dieser gefunden, wird der port erhöht?
Nur wenn alle verketteten Listen durchsucht wurden und KEIN port
gefunden wurde, wird port zurückgegeben? Also ist die Funktion "Suche
den Port, der NIRGENDWO enthalten ist"? Ich kenne den Gesamtzusammenhang
hier nicht, aber ich denke, daß dort auch ein definiertes
Abbruchkriterium fehlt, den im Extremfall wird das eine Endlosschleife,
wenn JEDER mögliche Port immer gefunden wird, auch wenn das extrem
selten ist.
Also besser so. Und siehe da, es ist genau so kompakt wie die
goto-Variante und definitv OHNE Gefahr einer Endlosschleife! Es geht
auch ohne Funktion zum Durchsuchern der verketteten Liste.
Daniel A. schrieb:> Ich bin dafür, sofern es den Code vereinfacht, lesbarer macht und nicht> zu oft verwendet wird.> Falk Brunner ist dagegen, sofern es nicht sinvoll oder notwendig ist?> Mark Brandis ist dagegen, wenn immer es ohne geht oder es von einem> Anfänger benutzt wird?> W.S. scheint für goto zu sein?> Zeno sympathisiert mit W.S. ?>> Habe ich das so richtig im Kopf?
Alles korrekt in der Birne. Hatte in dem Post ja auch nicht Dich
angesprochen. Sieh Dir doch nur an wie man sich zwischenzeitlich schon
ein ein paar Zeilen Code aufgeilt. Langsam wird es peinlich.
Programmierer schrieb:> Im Prinzip ist es einfach: Wer "goto" verteidigt und nicht missbilligt,> muss noch ein paar Sprossen die Leiter der Erkenntnis nach oben> klettern.
Glückwunsch! Du scheinst ganz oben auf der Leiter zu stehen. Aber
Vorsicht noch ein Schritt, dann bist Du auch ganz schnell wieder unten.
nichtCler schrieb:> Noch furchtbarer als meine Kommentare? Das macht mir Angst und stelle> deshalb das Schreiben in diesem thread ein.
Ach Du darfst ruhig weiter schreiben. Wir machen doch alle Fehler - gilt
auch bei Rechtschreibung.
M. K. schrieb:> Durchs Knie ins Auge schießen kann man in C nicht nur mit goto, das geht> mit allen Schleifen prima.
Geht in allen Programmiersprachen.
sepp schrieb:> Wie du in deinem Beitrag selbst schon schreibst ist es wichtig gut> strukturierte Software zu schreiben und du zeigst ja auch das man ohne> goto einiges falsch machen kann. Goto kann falsch angewendet, schnell zu> schlecht strukturierter Code führen aber in einigen Fällen auch sehr> hilfreich sein um gut strukturierten Code zu erzeugen.
Richtig! Ist halt immer wieder schön wenn jemand heraus findet, das sich
ein selbst ernannter Gott mal wieder klassisch ins Knie gebohrt hat.
Mark B. schrieb:> Die bisherigen Beispiele sind kein Beweis, denn sie sind entweder> unvollständig oder verstoßen gegen Best Practice-Regeln des Software> Designs oder beides.
Da Du generell gegen die Verwendung von goto bist, wird sich kein Code
mit goto finden lassen der Deinen sturen Ansichten genügt.
@MCUA, @blablablubb : Laßt es! Mark weiß es immer besser, es gilt nur
seine Meinung. Das Beste wird wohl sein Burschen links liegen zu lassen.
Mikro 7. schrieb:> In den Referenzen findet man dann auch u.a. Linus' Statement dazu:>> I think goto's are fine
Schau in den Folgepost und Du wirst sehen auch hierzu hat Mark ein
Statement - er weis es natürlich besser. Aber jetzt scheinen ihm langsam
die Argumente auszugehen und deshalb muß jetzt dies
Mark B. schrieb:> Linus Torvalds hat nie ein Buch über Software-Design geschrieben. Oder> über Software-Architektur. Oder darüber, wie man Software richtig> testet.
herhalten. Linus T. ist ja auch nur so ein Dau der von nichts eine
Ahnung hat.
Mark B. schrieb:> Warum wohl? ;-)
Er ist ja der Vater des Linuxkerns und das ist BS und das ist ja nach
Ansicht einige Leute hier auch was ganz anders.
Allerdings zeugt Linus's Äußerung zu Pascal und zu seinem Erfinder
Niklaus Wirth auch nicht von guter Kinderstube. Niklaus Wirth war
sicherlich nicht geistig unterbelichtet.
Zeno
Falk B. schrieb:> Also ist die Funktion "Suche> den Port, der NIRGENDWO enthalten ist"?
Wenn man in TCP eine neue Verbindung zu einem anderen Host herstellen
will, muss man zuerst ein noch nicht benutztes source/destination
address pair suchen. Da dieser Code, sofern nicht jede destination
address eigene tcp_pcb_lists hat, die destination addresse ignoriert,
kann man das System Lahmlegen indem man es dazu bringt 2^16-1
Verbindungen herzustellen, falls dies vom restlichen Code her überhaupt
möglich ist.
Als Rückgabe wert im falle eines Fehlers wäre hier 0 geeignet, da dieser
Port ansonsten nicht verwendet werden darf.
Falk B. schrieb:> Und jetzt werden die Goto-ianer wieder über die Hilfsvariable found> lästern ;-)
Nö warum? Eine Hilfsvariable kann doch durchaus Sinn machen unabhängig
von while, for, goto etc.
Falk B. schrieb:> Aber ich muß gestehen, daß ich den Sinn dieses Programmabschnitts noch> nicht so ganz verstehe.
Ich sagte doch, das ich das Beispiel willkürlich aus den Sourcen
herausgegriffen habe. Irgendwie geht es in der Gesamtdatei um den TCP
Stack. Aber wirklich kann ich das nicht beurteilen und würde es mir auch
nicht anmaßen. Da hilft nur eins selbst die Quellen anschauen.
@ Daniel Abrecht (daniel-a)
>kann man das System Lahmlegen indem man es dazu bringt 2^16-1>Verbindungen herzustellen, falls dies vom restlichen Code her überhaupt>möglich ist.
Diverse Sicherheitslecks und andere Bugs basieren auf so etwas.
Solider, bombenfester Code vermeidet sowas sicher.
Mark B. schrieb:> Dann zeig mir eins. Ein Beispiel mit goto, wo man keine andere> Unterteilung des Codes in Funktionen, kein anderes Software Design hätte> wählen können, das besser gewesen wäre.
Das habe ich bewusst nicht getan und werde es auch nicht tun. Und das
hat zwei Gründe:
- Es wurde schon oft genug getan.
- Du wirst dir eine "schönere" Lösung mit Hilfsvariablen und Splittung
in Funktionen aus den Fingern saugen, die in Wirklichkeit nicht schöner
ist, sondern nur dazu dient dir ein gutes Gefühl zu geben.
blablablubb schrieb:> Mark B. schrieb:>> Dann zeig mir eins. Ein Beispiel mit goto, wo man keine andere>> Unterteilung des Codes in Funktionen, kein anderes Software Design hätte>> wählen können, das besser gewesen wäre.>> Das habe ich bewusst nicht getan und werde es auch nicht tun. Und das> hat zwei Gründe:> - Es wurde schon oft genug getan.> - Du wirst dir eine "schönere" Lösung mit Hilfsvariablen und Splittung> in Funktionen aus den Fingern saugen, die in Wirklichkeit nicht schöner> ist, sondern nur dazu dient dir ein gutes Gefühl zu geben.
Im Gegensatz zu Euch habe ich Argumente dafür genannt, warum es so
besser ist wie ich es beschreibe.
Wen eine bessere Modularität und eine bessere Testbarkeit des Codes
nicht überzeugen, der ist wohl von der Mentalität der "Nach mir die
Sintflut" Programmierer. "Wozu Unit Tests? Mein Code funktioniert auch
so!"
Kenne ich, habe ich schon diverse Kollegen gehabt die so arbeiten. Die
meisten von ihnen sind zum Glück nicht mehr da. Qualität setzt sich
irgendwann eben doch durch, bzw. Mangel an Qualität fliegt raus.
Mark B. schrieb:> Im Gegensatz zu Euch habe ich Argumente dafür genannt, warum es so> besser ist wie ich es beschreibe.
Die Argumente für goto sind älter als das Internet und wurden schon
millionenfach genannt. Das braucht man nicht mehr zu wiederholen.
> Wen eine bessere Modularität und eine bessere Testbarkeit des Codes> nicht überzeugen, der ist wohl von der Mentalität der "Nach mir die> Sintflut" Programmierer. "Wozu Unit Tests? Mein Code funktioniert auch> so!"
Es ist doch völlig absurd zu behaupten der Code würde irgendwie magisch
besser testbar, wenn man kein goto verwendet.
Um es mit Linus' Worten zu sagen: Only a moron would believe that.
blablablubb schrieb:> Es ist doch völlig absurd zu behaupten der Code würde irgendwie magisch> besser testbar, wenn man kein goto verwendet.
Das hat auch keiner so behauptet. Lerne lesen und Zusammenhänge
verstehen, dann komm wieder.
Mark B. schrieb:> Das hat auch keiner so behauptet.
Doch das hast du. Zitat:
>Im Gegensatz zu Euch habe ich Argumente dafür genannt, warum es so>besser ist wie ich es beschreibe.>Wen eine bessere Modularität und eine bessere Testbarkeit des Codes>nicht überzeugen, der ist wohl von der Mentalität der "Nach mir die>Sintflut" Programmierer.
Und jetzt höre auf zu lügen.
Noch einmal zu dem von Zeno geposteten Beispielcode aus lwIP:
Ein Rückwärts-Goto ist böser als ein Vorwärts-Goto, da er eine Schleife
kaschiert. Für Schleifen stellt C aber genügend Konstrukte zur Auswahl
(for, while, do), von denen praktisch immer eines passend ist.
Und die Prüfung, ob der jeweils betrachtete Port schon benutzt wird,
schreit gerade danach, in eine eigene Funktion ausgelagert zu werden.
Deswegen sähe mein Vorschlag so aus:
Die Funktion port_is_in_use enthält zwar immer noch einen verkappten
Goto, nämlich die Return-Anweisung inmitten der inneren Schleife. Zum
einen ist das aber ein Vorwärtssprung, der nicht ganz so böse ist, zum
anderen ist die Funktion so kurz, dass trotz dieses Schönheitsfehlers
ihre Ablaufstruktur mit einem Blick erfasst werden kann.
Man könnte natürlich die innere Schleife in eine weitere Funktion
auslagern und käme dann mit jeweils einem Break als Schleifenabbruch
aus. Bei dieser kurzen Funktion halte ich es aber für übertrieben, sie
weiter aufzuteilen.
Welche der drei Versionen (Original, von Falk und die obige) am besten
lesbar ist, muss jeder subjektiv für sich entscheiden.
Effizienz ist in diesem Fall übrigens kein Argument für den Goto im
Originalcode, denn der GCC erzeugt aus dem obigen Quelltext
erwartungsgemäß den gleichen Assemblercode.
Hier ist der Vollständigkeit halber noch der Kommentar über dem
Originalcode dieser Funktion:
1
/*
2
* tcp_new_port():
3
*
4
* A nastly hack featuring 'goto' statements that allocates a
Mark B. schrieb:> Wen eine bessere Modularität und eine bessere Testbarkeit des Codes> nicht überzeugen, der ist wohl von der Mentalität der "Nach mir die> Sintflut" Programmierer. "Wozu Unit Tests? Mein Code funktioniert auch> so!">> Kenne ich, habe ich schon diverse Kollegen gehabt die so arbeiten. Die> meisten von ihnen sind zum Glück nicht mehr da. Qualität setzt sich> irgendwann eben doch durch, bzw. Mangel an Qualität fliegt raus.
Unit Tests ist kein Garant für fehlerfreien Code, denn den Testfall
generiert der Programmierer und wenn der einen Fehler in seinem
Denkansatz hat, dann geht es halt in die Hose.
Zeno schrieb:> Unit Tests ist kein Garant für fehlerfreien Code
Nicht unbedingt. Es ist häufig unrealistisch jeden möglichen Ausgabewert
zu jedem möglichen Eingabewert zu überprüfen. Es kann durchaus
passieren, dass ein Fehler bei einem Spezialfall enthalten ist, den man
beim Testcase nict bedacht hatte oder nicht wissen konnte.
Yalu X. schrieb:> Welche der drei Versionen (Original, von Falk und die obige) am besten> lesbar ist, muss jeder subjektiv für sich entscheiden.
Genau so ist es.
>> Effizienz ist in diesem Fall übrigens kein Argument für den Goto im> Originalcode, denn der GCC erzeugt aus dem obigen Quelltext> erwartungsgemäß den gleichen Assemblercode.
Das vermag ich nicht zu beurteilen.
>> Hier ist der Vollständigkeit halber noch der Kommentar über dem> Originalcode dieser Funktion:
Endlich mal einer der nicht stur irgend etwas behauptet, sondern sich
die Mühe macht mal die Quellen des Codeschnipsels anzusehen und erst
dann sein Statement abgibt.
Zeno
Daniel A. schrieb:> Es ist häufig unrealistisch jeden möglichen Ausgabewert> zu jedem möglichen Eingabewert zu überprüfen. Es kann durchaus> passieren, dass ein Fehler bei einem Spezialfall enthalten ist, den man> beim Testcase nict bedacht hatte oder nicht wissen konnte.
Genau das habe ich doch geschrieben - halt anders formuliert.
Walter S. schrieb:> Falk B. schrieb:>> War noch ein kleiner Fehler drin 8-0>> So ist es richtig>> fast ;-)> i wird doppelt verwendet
Ist ja voll einfach, übersichtlich und elegant, so ein Quellcode ohne
goto.
blablablubb schrieb:> Mark B. schrieb:>> Das hat auch keiner so behauptet.>> Doch das hast du. Zitat:>>>Im Gegensatz zu Euch habe ich Argumente dafür genannt, warum es so>>besser ist wie ich es beschreibe.>>Wen eine bessere Modularität und eine bessere Testbarkeit des Codes>>nicht überzeugen, der ist wohl von der Mentalität der "Nach mir die>>Sintflut" Programmierer.>> Und jetzt höre auf zu lügen.
Erzähl doch keinen Käs.
Ich habe mehrere Male in diesem Thread gesagt, dass es in der Regel ein
schlechtes Software-Design ist, das zur Verwendung von goto führt. Wenn
man zu viel Code in eine einzelne Funktion hineinpackt, à la:
-Öffnen einer oder mehrer Ressource(n)
-Lesen von einer, oder Schreiben auf eine Ressource
-Behandlung von Fehlerfällen
-Schließen der Ressource(n)
dann kommt man leicht zu stark verschachteltem Code, wo man vielleicht
dann gerne mal dazu geneigt ist, mit goto "auszubrechen". Man muss das
Ganze aber nicht so aufziehen. Ein Refactoring führt zu besserem Code,
der stärker modularisiert ist. In einem solchen Code wird goto zu
99,999% überflüssig sein.
Natürlich steht es Dir frei, solche Argumente einfachb zu ignorieren,
wie Du es ja auch tust. Dann ist eine Diskussion freilich sinnlos.
Zeno schrieb:> Unit Tests ist kein Garant für fehlerfreien Code
Das ist schon richtig. Aber das hat auch niemand behauptet, dass dies
ein Garant wäre. Und deswegen...
> denn den Testfall> generiert der Programmierer und wenn der einen Fehler in seinem> Denkansatz hat, dann geht es halt in die Hose.
...gibt es nach dem Unit Test noch einen Integrationstest und/oder
entsprechend Regressionstests, die von jemand anderem als dem Entwickler
durchgeführt werden.
So üblich in der Medizintechnik, im Automotive-Bereich, Luft- und
Raumfahrt, Automatisierungstechnik, Schienenverkehrstechnik,
Analytischen Messtechnik, ...
@Yalu X. (yalu) (Moderator)
>Und die Prüfung, ob der jeweils betrachtete Port schon benutzt wird,>schreit gerade danach, in eine eigene Funktion ausgelagert zu werden.
Eben.
>Deswegen sähe mein Vorschlag so aus:>static bool port_is_in_use(u16_t port) {
Ist OK.
>static u16_t tcp_new_port(void) {> static u16_t port = TCP_LOCAL_PORT_RANGE_START;> do {> if (port++ >= TCP_LOCAL_PORT_RANGE_END)> port = TCP_LOCAL_PORT_RANGE_START;> } while(port_is_in_use(port));> return port;>}
Das hat wieder das Zeug zur Endlosschleife.
>/*> * tcp_new_port():> *> * A nastly hack featuring 'goto' statements that allocates a> * new TCP local port.> */
ERWISCHT!
;-)
Mark B. schrieb:> Erzähl doch keinen Käs.>> Ich habe mehrere Male in diesem Thread gesagt,>blabla
Das bestreite ich alles nicht. UND du hast gesagt, dass der Code besser
testbar ist, wenn kein goto verwendet wird. Und nur auf diese Aussage
bezog ich mich. Sie ist halt Unsinn.
Yalu X. schrieb:> Und die Prüfung, ob der jeweils betrachtete Port schon benutzt wird,> schreit gerade danach, in eine eigene Funktion ausgelagert zu werden.
@blablablubb
Da hast Du's. Wenn Du mir schon nicht glauben willst, dann glaub
wenigstens Yalu.
Mark B. schrieb:> ...gibt es nach dem Unit Test noch einen Integrationstest und/oder> entsprechend Regressionstests,>...
Und was hat das alles mit dem Thema zu tun?
Es geht hier um goto.
Mark B. schrieb:> Da hast Du's. Wenn Du mir schon nicht glauben willst, dann glaub> wenigstens Yalu.
Der Missbrauch von goto als Schleifenkonstrukt ist nicht schön. Das habe
ich nie bestritten.
Aber es gibt viele legitime Einsatzgebiete für goto. Diese wurden alle
schon genannt und sind trivial auffindbar.
blablablubb schrieb:> Das bestreite ich alles nicht. UND du hast gesagt, dass der Code besser> testbar ist, wenn kein goto verwendet wird.
Nein. Du verstehst "Ursache und Wirkung" nicht, kann das sein?
1.) Ursache: Schlechtes SW-Design - zu viel Code/zu viel Funktionalität
in einer Funktion
2.) Wirkung: Je nach Programmierer --> Unnötige Verwendung von goto,
oder anderweitig miese Code-Qualität
3.) Heilung: Besseres SW-Design --> Kleinere Funktionen, Weniger stark
verschachtelter Code, goto wird unnötig (falls es je nötig war ;-)
4.) Nebeneffekt: Kleinere Funktionen sind besser für Unit Tests.
Es ist nicht so schwer zu verstehen - wenn man mal drüber nachdenken
mag.
blablablubb schrieb:> Aber es gibt viele legitime Einsatzgebiete für goto. Diese wurden alle> schon genannt und sind trivial auffindbar.
Mit "viele" meinst Du sicher:
-Kernel Hacking unter Linux
-Kernel Hacking unter OpenBSD
-Kernel Hacking unter FreeBSD
-Kernel Hacking unter NetBSD
-Kernel Hacking unter blablablubb OS
;-)
Mark B. schrieb:> 1.) Ursache: zu viel Code/zu viel Funktionalität in einer Funktion> 2.) Wirkung: Unnötige Verwendung von goto,
Das ist doch an den Haaren herbeigezogener Mumpitz. Es besteht doch kein
Zusammenhang zwischen der Funktionalitätsmenge und goto. Schon gar nicht
in dem Sinne, dass viel Funktionalität ein goto bedingt, was du ja
implizierst.
Mark B. schrieb:> Mit "viele" meinst Du sicher:>...
Ja, unter anderem. Endlich hast du mal ein paar der immer wieder
vorgetragenen Beispiele gefunden. Bravo.
blablablubb schrieb:> Mark B. schrieb:>> 1.) Ursache: zu viel Code/zu viel Funktionalität in einer Funktion>> 2.) Wirkung: Unnötige Verwendung von goto,>> Das ist doch an den Haaren herbeigezogener Mumpitz. Es besteht doch kein> Zusammenhang zwischen der Funktionalitätsmenge und goto.
Der Zusammenhang besteht zum Beispiel über die Verschachtelungstiefe,
aus der mancher Programmierer (ich nicht) gerne mit goto "ausbricht".
Mark B. schrieb:> aus der mancher Programmierer (ich nicht) gerne mit goto "ausbricht".
Ja, das ist doch aber kein Muss.
Nur weil einige das machen, muss man doch goto nicht verteufeln.
Der Ansatz von Yalu ist gut, die endgültige Funktion aber unsicher :-(
Besser so. Das ist wasserdicht, auch wenn man eher selten 64k Ports
benutzen wird. Das ist so ähnlich wie die seltenen, nicht atomaren
Zugriffsfehler auf ISR Variablen . . .
Mark B. schrieb:> ...gibt es nach dem Unit Test noch einen Integrationstest und/oder> entsprechend Regressionstests, die von jemand anderem als dem Entwickler> durchgeführt werden.
Wie viele Tests hättest Du denn gern. Es wird keinen 100% fehlerfreien
Code geben, das müssen wir nun halt mal akzeptieren.
Ohne jetzt hier noch einen Streit über die Qualität von
Programmiersprachen vom Zaune brechen zu wollen behaupte ich jetzt mal,
das die Qualität des Codes und/oder die Fehlerhäufigkeit schon davon
abhängig ist, was der jeweilige Compiler / Interpreter an Schweinereien
im Code zuläßt.
Und da kannst Du Testszenarien ohne Ende machen, wenn ein ein spezieller
Fall nicht bedacht wird, wird es krachen wenn er denn eintritt.
Ich hab jetzt auch so einen Fall wo ein ganz Schlauer meint mit C# und
Unit Test wird alles gut. Denkste! Mit 2 Klicks bringe ich das Programm
zum Absturz und zwar so das es nicht mehr startbar ist und neu
installiert werden muß.
Zeno
blablablubb schrieb:> Falk B. schrieb:>> u16_t i;>>>> for (...; i>0; ...) {>> Ach bitte...
Wie würdest du es schreiben? Ich würde vermutlich sowas machen:
Daniel A. schrieb:> u16_t i;> for( i=0; --i; ) {
Ach du lieeebe Zeit.
Rückwärtszählende Schleifen.
Schleifen, die Überlauf ausnutzen.
Das kommt dabei raus, wenn man krampfhaft versucht goto oder
early-return zu vermeiden.
Warum nicht einfach ganz trivial vorwärts zählen und bei
Abbruchbedingung die Funktion sofort mit early-return verlassen? Das
wäre vermutlich zu einfach.
Hallo,
ich würde dem bereits praktizierten Logikfehler „bei Praktikern schauen”
gern ganz kurz noch ein weiteres Kapitel anfügen.
Gotos getestet mit grep -R "goto \\w\\+;" * | wc -l
und kurzer Sichtkontrolle ohne wc:
apache-httpd 265
git 760
gnu scientific library 69
mysql server 7215
postgreSQL 2542
glibc 2070
mehr großer und etablierter c-Code fiel mir so schnell nicht ein.
Wahnsinn, dieses krasse Stümpertum überall.
vlg
Timm
rhf schrieb:> Herbert P. schrieb:>>> Nicht zuletzt deshalb gilt diese Regel auch in meinen Vorlesungen>> und Übungen, obwohl sie meine Studierenden auch immer wieder gerne>> wegdiskutieren wollen...>> Was habe ich diese auf Formalien herum reitenden Professoren während> meines Studiums gehasst. Meistens waren das auch genau die, bei denen> ich am wenigsten gelernt habe, da sie aus ihrer fachlichen "Ecke" nicht> heraus kamen. Aber egal.
Nun ja, Ansichtssache. Ich sehe das nicht als Formalie. Über die Jahre
habe ich Pascal, Fortran, Prolog, Assembler, PL/I, C und andere
praktisch in der Industrie verwendet. Mit und ohne goto, und ich habe
meine Lektion gelernt. Ich finde aber, das es nicht notwendig ist, dass
meine Studis alle meine Fehler wiederholen müssen. Die meisten verstehen
es, und ein paar wenige brauchen halt etwas Nachdruck.
> Ich hätte aber einen Vorschlag für dich: Wenn du so davon überzeugt bist> das die Verwendung von goto absolut abzulehnen ist, lasse doch von> deinen Studenten einfach mal ein nicht triviales Programm schreiben in> dem ausschließlich goto erlaubt ist. Ich finde mit einen solchen> Beispiel könnte man doch sicherlich sehr anschaulich zeigen was für oder> gegen die Verwendung von goto spricht.>>
Das ist gar keine dumme Idee. Ich danke dir für diese Anregung. Das
werde ich wirklich mal ausprobieren. Bin gespannt, was dabei
herauskommt. :D
Herby
Timm R. schrieb:> apache-httpd 265> git 760> gnu scientific library 69> mysql server 7215> postgreSQL 2542> glibc 2070>> mehr großer und etablierter c-Code fiel mir so schnell nicht ein.> Wahnsinn, dieses krasse Stümpertum überall.
Nochmal für alle, die es immer noch nicht verstanden haben:
Quantität bezeugt keine Qualität.
Falk B. schrieb:> Der Ansatz von Yalu ist gut, die endgültige Funktion aber unsicher :-(
Mir ging es nicht darum, Fehler in dem Code zu korrigieren, sondern zu
zeigen, wie man das Goto eliminieren kann, ohne dabei am Verhalten der
und der Effizienz der Funktion etwas zu ändern.
Natürlich hast du recht, die Funktion läuft in eine Endlosschleife, wenn
alle Ports belegt sind. Der Fehler ist im Original auch längst behoben:
http://git.savannah.gnu.org/cgit/lwip.git/commit/src/core/tcp.c?id=112158b056c7b55498537cdb60e106b8075f465d
Witzigerweise wurde im gleichen Aufwasch auch der Kommentar mit dem
"nastly hack featuring 'goto' statements" entfernt, die Goto-Anweisung
selber wurde aber beibehalten :)
> for (i=0xFFFF; i>0; i--) {> if (port++ >= TCP_LOCAL_PORT_RANGE_END) {> port = TCP_LOCAL_PORT_RANGE_START;> }> if (!port_is_in_use(port)) break;> }
Das stimmt so nicht, denn es werden nicht alle 65535 Ports, sondern nur
diejenigen im Bereich von TCP_LOCAL_PORT_RANGE_START bis einschließlich
TCP_LOCAL_PORT_RANGE_END verwendet.
Yalu X. schrieb:> Witzigerweise wurde im gleichen Aufwasch auch der Kommentar mit dem> "nastly hack featuring 'goto' statements" entfernt, die Goto-Anweisung> selber wurde aber beibehalten :)
Im Grunde genommen ist das nur halt leider nicht witzig, sondern ein
Armutszeugnis.
Ich bin überzeugt davon, dass viele der von Timm Reinisch gelisteten
Vorkommen von goto von einer ähnlich "guten" Qualität sind.
Es zeigt sich leider immer wieder: Auf Codequalität achtet so gut wie
kein Schwein. :-(
Um wirklich nicht mehr in die Goto-Versuchung zu kommen, würde ich mir
ein solches Sprachmittel wünschen (in Pseudocode):
1
Procedure Foo()
2
3
if xy then EXIT
4
5
POSTEXIT
6
Cleanup...
7
End Procedure
D.h. dass man einen Bereich am Ende der Funktion/Routine definieren
kann, welcher bei einem Exit aus der Funktion raus noch abgearbeitet
wird. Das hielte ich auch für sauberen Code, da klar ist, wohin
gesprungen wird.
Mark B. schrieb:> Nochmal für alle, die es immer noch nicht verstanden haben:>> Quantität bezeugt keine Qualität.
Du behauptest also ernsthaft, dass folgende Projekte qualitativ
minderwertig sind?
> apache-httpd 265> git 760> gnu scientific library 69> mysql server 7215> postgreSQL 2542> glibc 2070
Ich würde es stark bezweifeln.
Hi,
Zeno schrieb im Beitrag #4547438:
> Mark B. schrieb:>>> Wahnsinn, dieses krasse Stümpertum überall.>>>> Nochmal für alle, die es immer noch nicht verstanden haben:>>>> Quantität bezeugt keine Qualität.>> Dieses Statement war doch klar - alles Stümper.> @Timm: Hast Du etwa was anderes erwartet?
Die Quantität der Fehler und Missverständnisse beim auf-teufel-komm-raus
Ausmerzen des einen Goto belegt eigentlich alles :-)
vlg
Timm
Tommi schrieb:> D.h. dass man einen Bereich am Ende der Funktion/Routine definieren> kann, welcher bei einem Exit aus der Funktion raus noch abgearbeitet> wird. Das hielte ich auch für sauberen Code, da klar ist, wohin> gesprungen wird.
Das gibt es doch schon, z.B. bei Objektpascal.
1
try
2
....
3
finally
4
....
5
end;
Man schreibt den kompletten Code für die Funktion zwischen try und
finally und das was man immer machen möchte, also unbedingt ausführen
möchte unabhängig davon ob während der Abarbeitung des Codes zw. try und
finally ein Fehler passiert oder nicht, kommt zw. finally und end. Der
Code zw. finally und end wird immer ausgeführt. Der im Codeteil der
Funktion evtl. gebildete Returnwert wird natürlich an die aufrufende
Funktion zurückgegeben, man kann ihn aber auch noch im finally/end-Block
ändern, was z.B. bei einem Fehler Sinn macht.
Zeno
Tommi schrieb:> D.h. dass man einen Bereich am Ende der Funktion/Routine definieren> kann, welcher bei einem Exit aus der Funktion raus noch abgearbeitet> wird.
Viele Sprachen mit Exceptions bieten dies. In Python heißt es "finally"
bzw. der Exception-Handler selbst. Und in Sprachen, die das nicht
bieten, kann mal es halt sehr schön mit goto machen. Da spricht absolut
nichts dagegen.
> Das hielte ich auch für sauberen Code, da klar ist, wohin> gesprungen wird.
Bei goto ist nicht klar wohin gesprungen wird??
Falk B. schrieb:> Schaff ich das noch heute noch?> u16_t i = TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START;>> for (; i>0; i--) {
Ich gehe mal davon aus, dass END und START der jeweils letzte und erste
gültige Port sind.
Dann zählt es eins zu wenig.
Also.
> Schaff ich das noch heute noch?
Viel Glück :)
Zeno schrieb:> und das was man immer machen möchte, also unbedingt ausführen> möchte unabhängig davon ob während der Abarbeitung des Codes zw. try und> finally ein Fehler passiert oder nicht, kommt zw. finally und end. Der> Code zw. finally und end wird immer ausgeführt.
Das ist allerdings kein Ersatz für einen per goto gebauten
fall-through-error-handler. (siehe Linux Kernel für Beispiele).
Zeno schrieb:> Das gibt es doch schon, z.B. bei Objektpascal.> [...]try [...] finally [...] end;
Geht halt nur für Exceptions. Im normalen Ablauf hat man ja nicht so
viele davon. Und mit Exceptions wild um sich zu werfen ist auch nicht
die Lösung.
blablablubb schrieb:> Bei goto ist nicht klar wohin gesprungen wird??
Nicht wenn man das Sprungziel nicht kennt. Es ann ja irgendwo stehen.
Von daher halte ich die Verwendung von Goto für in Ordnung, wenn man
immer nach vorne springt und idealerweise ans Ende der Funktion. Wenn
man sich an diese Konvention hält, weiß man wo sich das Sprungziel
befindet ohne direkt zu schauen. Das ist ja gerade der Vorteil von EXIT
und BREAK.
blablablubb schrieb:> Das ist allerdings kein Ersatz für einen per goto gebauten> fall-through-error-handler. (siehe Linux Kernel für Beispiele).
An dieser Stelle (Linuxkernel) kann ich nicht wirklich mit reden
Aber bei meinem Beispiel kann man, sofern Fehler passieren schon genau
festlegen was gemacht werden soll, da ja der finally Zweig im Fehlerfall
sofort angesprungen wird. Man wertet dann einfach die Exceptionvariable
aus und fertig.
Man kann ja zuerst die Exceptionvariable auslesen und entsprechend
behandeln und danach seinen Aufräumcode abarbeiten.
Was spricht dagegen das die Funktion einen Record zurückgibt, der das
Exceptionobject und den Rückgabewert der Funktion enthält? Man hat dann
alle Möglichkeiten der Fehlerbehandlung.
Zeno
Tommi schrieb:> Es ann ja irgendwo stehen.
Nein kann es nicht. Es muss innerhalb in der Funktion stehen. Und wenn
man es dort nicht findet, sollte man wegen Unfähigkeit aufhören zu
programmieren.
> Von daher halte ich die Verwendung von Goto für in Ordnung, wenn man> immer nach vorne springt und idealerweise ans Ende der Funktion.
So sehe ich das auch.
Zeno schrieb:> da ja der finally Zweig im Fehlerfall> sofort angesprungen wird.
Und es wird auch im Nicht-fehler-fall angesprungen. Und das kann ein
Problem sein.
Einen exklusiven Fehlerpfad kann man nur mit vielen Unterfunktionen oder
einer komplexen Unterfunktion machen, wenn man goto nicht verwendet. Und
selbst dann ist er unschön im Vergleich mit einer
goto-fallthrough-Lösung.
Zeno schrieb:> Was spricht dagegen das die Funktion einen Record zurückgibt, der das> Exceptionobject und den Rückgabewert der Funktion enthält? Man hat dann> alle Möglichkeiten der Fehlerbehandlung.
Dagegen spricht, dass das nicht der Fall ist, den
fall-through-error-handler behandelt. Er behandelt die Fehler
innerhalb der Funktion.
Tommi schrieb:> Geht halt nur für Exceptions. Im normalen Ablauf hat man ja nicht so> viele davon. Und mit Exceptions wild um sich zu werfen ist auch nicht> die Lösung.
Also bei Objectpascal gibt jede Menge Exceptions. Es gibt aber ein paar
Sachen wo selbige nicht generiert werden, z.B. bei den klassischen
Dateigeschichten wie reset, close, blockread etc.. Da kann man aber
Fehler über IOResult abfangen und sobald selbiges ungleich 0 ist eine
Exception generieren und schon landet man im finally-Block. Das heißt ja
jetzt nicht das man damit wild mit Exception um sich wirft.
Man kann IOResult aber auch in einer Variable speichern, die man dann im
finally-Block abfragt.
Noch einmal der finally-Block wird immer! durchlaufen unabhängig davon
ob eine Exeption aufgetreten ist oder nicht.
Zeno
blablablubb schrieb:> Dagegen spricht, dass das nicht der Fall ist, den> fall-through-error-handler behandelt. Er behandelt die Fehler> innerhalb der Funktion.
Okey! Ich kann die Fehlerbehandlung auch innerhalb der Funktion im
finally-Block durchführen. Es ist auch kein Problem wenn während der
Fehlerbehandlung eine andere Funktion erforderlich wäre, der
finally-Block wird in jedem Fall vollständig durchlaufen, es sei denn
ich produziere auch dort Fehler, dann knallt es halt. Allerdings kann
ich auch im finally-Block kritischen Code mit try/finally oder
try/except kapseln, d.h. ich Exceptionblöcke schachteln.
Zeno
blablablubb schrieb:> Und es wird auch im Nicht-fehler-fall angesprungen. Und das kann ein> Problem sein.
Es ging ja darum eine Funktion zu haben, die immer aufräumt bevor sie
verlassen wird. War dieser Post auf den ich da geantwortet habe.
Tommi schrieb:> Um wirklich nicht mehr in die Goto-Versuchung zu kommen, würde ich mir> ein solches Sprachmittel wünschen (in Pseudocode):> Procedure Foo()>> if xy then EXIT>> POSTEXIT> Cleanup...> End Procedure>> D.h. dass man einen Bereich am Ende der Funktion/Routine definieren> kann, welcher bei einem Exit aus der Funktion raus noch abgearbeitet> wird. Das hielte ich auch für sauberen Code, da klar ist, wohin> gesprungen wird.
Naja es ist halt wie immer, man muß schon wissen was man tut. Ich
benutze das Konstrukt gerne wenn ich Ressourcen, Zeiger etc. in jedem
Fall freigeben möchte.
Zeno
Daniel A. schrieb:> Ich denke es geht um soein Konstrukt?
Könnte man problemlos im try/finally-Konstrukt umsetzen - vielleicht
nicht ganz so elegant wie Du das in Deinem Beispiel gemacht hast.
Oder man macht es genauso mit goto - geht in Pascal auch.
Zeno
Daniel A. schrieb:> Ich denke es geht um soein Konstrukt?
Fast.
Ein ähnliches Konstrukt, das im Nicht-Fehlerfall keine Aufräumarbeiten
macht, geht mit finally nur mit zusätzlichen Krücken.
blablablubb schrieb:> Ein ähnliches Konstrukt, das im Nicht-Fehlerfall keine Aufräumarbeiten> macht, geht mit finally nur mit zusätzlichen Krücken.
Na dann bin ich mal froh, das mein Konstrukt im (nicht) Fehlerfall alle
Aufräumarbeiten macht ;)
blablablubb schrieb:> Du hast es nicht verstanden.
Ach so, es ging darum dass die Klammern bei try - finally verhindern,
dass man ein Cleanup auslassen kann...
blablablubb schrieb:> Ein ähnliches Konstrukt, das im Nicht-Fehlerfall keine Aufräumarbeiten> macht, geht mit finally nur mit zusätzlichen Krücken.
Eigentlich nicht.
1
try
2
try
3
....//beliebiger Code
4
except
5
....//aufräumen (nur im Fehlerfall)
6
end;
7
finally
8
....//alles was man sonst so noch machen will(auch bei Fehler)
Zeno schrieb:> Eigentlich nicht.
ja bla.
Man kann das natürlich hinfrickeln, dass es geht. z.B. wie in deinem
Beispiel mit einem verschachtelten try-Block. Oder mit einer
zusätzlichen Variablen.
So elegant wie mit goto geht es allerdings nicht.
blablablubb schrieb:> So elegant wie mit goto geht es allerdings nicht.
Das habe ich ja auch nicht behauptet. Habe eigentlich von Anfang an in
Frage gestellt ob ich Daniels Beispiel mit try so elegant hinbekomme.
Habe im Übrigen kein Problem damit, das er es mit goto's gelöst hat. Ich
finde ein schönes Beispiel wie man goto einsetzen kann.
Aber warte mal ab bis die Götter des Nicht-goto's wieder erwacht sind.
blablablubb schrieb:> Mark B. schrieb:>> Nochmal für alle, die es immer noch nicht verstanden haben:>>>> Quantität bezeugt keine Qualität.>> Du behauptest also ernsthaft, dass folgende Projekte qualitativ> minderwertig sind?
Ich sage nichts anderes, als dass auch schlechter Code funktionieren
kann. Beweise dafür gibt es hunderttausendfach. Einfach mal die Augen
öffnen.
Zeno schrieb im Beitrag #4547438:
> Mark B. schrieb:>>> Wahnsinn, dieses krasse Stümpertum überall.>>>> Nochmal für alle, die es immer noch nicht verstanden haben:>>>> Quantität bezeugt keine Qualität.>> Dieses Statement war doch klar - alles Stümper.> @Timm: Hast Du etwa was anderes erwartet?
Trolle zeichnen sich unter anderem dadurch aus, dass sie anderen Leuten
Worte in den Mund legen. Es wäre nett, wenn Du woanders weitertrollen
könntest.
Mark B. schrieb:> Ich sage nichts anderes, als dass auch schlechter Code funktionieren> kann.
Warum soll denn eine Lösung mit goto schlechterer Code sein?
Mark B. schrieb:>> Du behauptest also ernsthaft, dass folgende Projekte qualitativ>> minderwertig sind?>> Ich sage nichts anderes, als dass auch schlechter Code funktionieren> kann.
Und damit implizierst du, dass die genannten Beispiele qualitativ
schlechten Code haben. Und das ist geradezu lächerlich.
Wenn du das nicht implizieren würdest, wäre dein Argument unbrauchbar
für diese Diskussion, in der es um goto geht.
Mark B. schrieb:> Trolle zeichnen sich unter anderem dadurch aus, dass sie anderen Leuten> Worte in den Mund legen. Es wäre nett, wenn Du woanders weitertrollen> könntest.
Ich lasse mir von Dir nicht den Mund verbieten.
Du bist derjenige der allen anderen stümperhaftes Programmieren
unterstellt, selbst Leuten die Software geschrieben haben, die seit
Jahren millionenfach erfolgreich im Einsatz ist und das sogar im
Serverbetrieb. Dafür das das Programmieren mit goto so stümperhaft ist
läuft diese Software außerordentlich stabil und zuverlässig, wie z.B.
der Apache Webserver, um nur ein Beispiel zu nennen. Die Leute die das
Teil programmiert haben können also nicht so viel falsch gemacht haben.
Ich glaube Du leidest an einer gehörigen Portion Selbstüberschätzung und
deshalb mußt Du Dich nicht wundern, wenn entsprechende Kommentare
kommen.
Du hälst stur an Deinen Dogmen fest und bist Dir offenbar zu fein mal
über den Tellerrand zu schauen. Aber warum solltest Du das auch tun,
denn die anderen sind ja eh alles Deppen. Fehlt nur noch das wir Dir
huldigen müssen.
Wir kennen mittlerweile Deine Meinung, wissen auch das Du auf selbiger
beharrst und in diesem Sinne solltest eher Du dich trollen, da Du diesen
Thread nicht weiter bereicherst.
Zeno
Mitlesender schrieb:> Dafür das das Programmieren mit goto so stümperhaft ist> läuft diese Software außerordentlich stabil und zuverlässig,
Nochmals. Wer etwas sagt, oder wieviele etwas sagen, spielt schlichtweg
keine Rolle.
Plakatives Beispiel: Wieviele Deutsche sind der Meinung, Spinat enthalte
besonders viel Eisen? Wie oft hat man schon gehört, Eskimos hätten
deutlich mehr Wörter für Schnee als Europäer?
Diese Meinungen werden Millionenfach vertreten, machen sie aber dennoch
nicht richtig. Sie sind in der Tat falsch.
Anderes Beispiel. 2+3 = 5. Daraus kannst Du aber nicht schließen, dass
jede 5 dieser Welt die Summe aus 2+3 ist. Eine 5 kann auch die Summe aus
1+4 sein.
Was Du machst, ist ein ganz banaler Argumentationsfehler. Aus "B folgt
aus A" kann man eben gerade nicht schließen, "A folgt aus B".
Programmierer schrieb:> Nochmals. Wer etwas sagt, oder wieviele etwas sagen, spielt schlichtweg> keine Rolle.
Doch das tut es.
Wenn eine Art eine Software zu entwickeln in Millionen von Codezeilen
äußerst erfolgreich eingesetzt wird, dann ist diese Art nicht schlecht
oder gar stümperhaft.
Die Software ist qualitativ hochwertig und funktional korrekt.
Der Vergleich mit irgendwelchen Volksweisheiten ist deshalb nicht
zutreffend, weil diese genannten Volksweisheiten eben nachweislich
falsch sind. (= nicht funktional korrekt)
Mark B. schrieb:> blablablubb schrieb:>> Aber es gibt viele legitime Einsatzgebiete für goto. Diese wurden alle>> schon genannt und sind trivial auffindbar.>> Mit "viele" meinst Du sicher:> -Kernel Hacking unter Linux> -Kernel Hacking unter OpenBSD> -Kernel Hacking unter FreeBSD> -Kernel Hacking unter NetBSD> -Kernel Hacking unter blablablubb OS
Nein, in erster Linie "Fehlerbehandlung unter Randbedingungen". In
zweiter Linie "Performancekriterium trumpft elegant-sauberen Code" (z.B.
Jump-Tables). In dritter Linie dann switch/case und early return, die ja
auch nix anderes sind. Beispiele gab es genug.
Es ist bewiesen, dass man immer ohne goto auskommen kann (und sei es
auf Kosten zusätzlicher Variablen, höherer Verschachtelungstiefe,
zusätzlichen Funktionsaufrufen etc.) und daher wirst du immer
argumentieren, dass man das goto dann auch wegmachen kann und der Code
zwingend besser wird.
Und das, lieber Mark, ist Religion.
Wir sind uns hier alle einig, dass man ohne goto auskommen kann.
Wir sind uns aber nicht einig, dass man für guten Code ohne goto
auskommen muss.
S. R. schrieb:> Wir sind uns hier alle einig, dass man ohne goto auskommen kann.> Wir sind uns aber nicht einig, dass man für guten Code ohne goto> auskommen muss.
Schön geschrieben!
Programmierer schrieb:> Nochmals. Wer etwas sagt, oder wieviele etwas sagen, spielt schlichtweg> keine Rolle.
Richtig, das Spielt keine Rolle. Und eine Sache wird auch nicht richtig
nur weil genügend dran glauben oder sagen es sei richtig. Die
Contra-goto-Fraktion macht hier aber etwas ähnliches indem sie sagt,
dass das Verwenden von goto generell schlechter Stil sei. Zumindest ich
lese das hier zwischen den Zeilen der Contra-goto-Fraktion heraus. Man
kann viel Mist mit goto machen, man kann es aber auch so intelligent
benutzen wie andere Dinge von C.
Programmierer schrieb:> Mitlesender schrieb:>> Dafür das das Programmieren mit goto so stümperhaft ist>> läuft diese Software außerordentlich stabil und zuverlässig,>> Nochmals. Wer etwas sagt, oder wieviele etwas sagen, spielt schlichtweg> keine Rolle.
Exakt so ist es. Endlich mal einer, der es verstanden hat.
> Was Du machst, ist ein ganz banaler Argumentationsfehler. Aus "B folgt> aus A" kann man eben gerade nicht schließen, "A folgt aus B".
Eben eine klassische "logical fallacy".
blablablubb schrieb:> Doch das tut es.> Wenn eine Art eine Software zu entwickeln in Millionen von Codezeilen> äußerst erfolgreich eingesetzt wird, dann ist diese Art nicht schlecht> oder gar stümperhaft.
Dieses Argument ist völlig an den Haaren herbei gezogen. Unter anderem
mal goto zu verwenden ist keine "Art zu programmieren."
> Die Software ist qualitativ hochwertig und funktional korrekt.
Möchtest Du bitte den Unterschied zwischen Binary und Sourcecode
verstehen?
Eine Software kann funktionieren, und sogar gut funktionieren - das
heißt aber noch lange nicht, dass auch der Sourcecode dazu von einer
hohen Qualität ist. Das sind einfach zwei verschiedene Dinge.
Die Schlussfolgerung "Weil Linux gut ist, dann muss auch die Art und
Weise wie der Linux Kernel programmiert ist gut sein" ist schlichtweg
unzutreffend. Das eine folgt einfach nicht aus dem anderen.
Falls Du schon mal davon gehört hast: Es gibt so genannte "Big Balls of
Mud". Das sind Software-Systeme, die von außen betrachtet mehr oder
weniger gut funktionieren, die aber im Inneren eine sehr bescheidene
Qualität aufweisen.
https://en.wikipedia.org/wiki/Big_ball_of_mud
Mark B. schrieb:> Die Schlussfolgerung "Weil Linux gut ist, dann muss auch die Art und> Weise wie der Linux Kernel programmiert ist gut sein" ist schlichtweg> unzutreffend.
Achso. Man kann also mit schlechtem Quelltext ein gutes Binary erzeugen.
Warum also dann die Diskussion um goto und Programmierstile, wenn es
doch egal ist, weil das Ergebnis ja ohnehin gut ist?
>Unter anderem>mal goto zu verwenden ist keine "Art zu programmieren."
sondern?
blablablubb schrieb:> Mark B. schrieb:>> Die Schlussfolgerung "Weil Linux gut ist, dann muss auch die Art und>> Weise wie der Linux Kernel programmiert ist gut sein" ist schlichtweg>> unzutreffend.>> Achso. Man kann also mit schlechtem Quelltext ein gutes Binary erzeugen.> Warum also dann die Diskussion um goto und Programmierstile, wenn es> doch egal ist, weil das Ergebnis ja ohnehin gut ist?
Jemand, der Ahnung von SW-Entwicklung hat, würde eine solche Frage nicht
stellen. Selbst der Dümmste versteht, dass es besser ist eine Codebasis
zu haben, die gut strukturiert, gut lesbar und gut zu warten ist.
Mit solchen Dummköpfen mag ich nicht länger diskutieren. Ich bin raus.
Mark B. schrieb:> Selbst der Dümmste versteht, dass es besser ist eine Codebasis> zu haben, die gut strukturiert, gut lesbar und gut zu warten ist.
Genau. Und deshalb setze ich goto ein, weil es den Quellcode lesbarer
und besser wartbar macht.
> Mit solchen Dummköpfen mag ich nicht länger diskutieren.
Lieber nicht mit Argumenten kommen, gell?
Huch, da schaut man mal wieder rein - und ihr diskutiert immer noch.
S. R. schrieb:> Wir sind uns hier alle einig, dass man ohne goto auskommen kann.> Wir sind uns aber nicht einig, dass man für guten Code ohne goto> auskommen muss.
Ja, ja und nochmals JA. Sowas hätte definitiv als ultimatives Schlußwort
gelten können für diesen Thread. Aber religiös angehauchte Eiferer wie
Mark bemerken nicht, wenn sie sich verstiegen haben.
Mitlesender schrieb:> Ich glaube Du leidest an einer gehörigen Portion Selbstüberschätzung und> deshalb mußt Du Dich nicht wundern, wenn entsprechende Kommentare> kommen.
Nun ja, du Mitlesender, ich meine da eine Feinkorrektur anbringen zu
müssen: Mark leidet nicht an seiner objektiv vorhandenen
Selbstüberschätzung. Vielmehr leidet er darunter, daß sie beim Rest der
Welt nicht so recht ankommen will und ihm das auch mehr oder weniger
dezent gesagt wurde.
Aber anstatt mal in sich zu gehen und sich zu fragen, WARUM sowas wie
"goto" in allen Progremmiersprachen (nun ja, jedenfalls in den nicht
rein Deklarativen) vorkommt, betitelt er den Rest der Welt als
Dummköpfe. Sind also alle Erfinder aller existierenden
Programmiersprachen stupide Dummköpfe???
So.
Eigentlich sollte man sich mal wieder an den gesunden Menschenverstand
erinnern. Goto gehört zum Sprachumfang und es sollte dem verständigen
Programmierer im jeweiligen Einzelfall überlassen bleiben, ob und wo er
es benutzt. Alle Pauschal-Verurteilungen sind Oberbockmist - und das
sollte es hier gewesen sein.
W.S.
W.S. schrieb:> Aber anstatt mal in sich zu gehen und sich zu fragen, WARUM sowas wie> "goto" in allen Progremmiersprachen (nun ja, jedenfalls in den nicht> rein Deklarativen) vorkommt,
Ersetze "allen" durch "vielen", denn es gibt durchaus imperative
Programmiersprachen ohne Goto, z.B. Java, Javascript, Python, Bash,
Rust, Groovy und Swift.
Mark B. schrieb:> Dieses Argument ist völlig an den Haaren herbei gezogen. Unter anderem> mal goto zu verwenden ist keine "Art zu programmieren."
Du kannst keine andere Meinung akzeptieren. Mehr kann man einfach nicht
dazu sagen. Jegliche weitere Diskussion ist deshalb zwecklos.
Zeno
Mark B. schrieb:> Mit solchen Dummköpfen mag ich nicht länger diskutieren. Ich bin raus.
Wenn es keine Argumente mehr hat dann Kopf in den Sand und beleidigt
sein. Aber in diesem Fall ist das gut so.
Wie man sich derart verbissen um den sinnlosen Returnwert von main() in
Programmen für betriebssystemfreie embedded-Umgebungen streiten kann ...
;-). Üblicherweise ist es doch so, dass der Compiler auch schon vor C99
nicht auf einem return besteht, weil er weiss, dass hinter der
Hauptschleife nix los ist.
Es gibt übrigens einen banalen Grund, weshalb man in Sprachen wie C das
"goto" nicht gänzlich streichen sollte: C Programme werden nicht nur von
Menschen geschrieben. In maschinell produziertem C Code kann goto
sinnvoll bis notwendig sein.
A. K. schrieb:> ... um den sinnlosen Returnwert ...
Der Returnwert war nur "Nebenprodukt". Eigentlich ging es um die
Verwendung von goto.
Ich meine W.S. hatte geschrieben, das er mit goto die Compilermecker
unterdrücken kann bei gleichzeitigem Verzicht auf return 0. Mehr
eigentlich nicht. Aber genau das hat die Hüter des "nicht goto" erst mal
so richtig auf den Plan gerufen. Verstehen kann ich das auch nicht.
Bisher habe ich auch immer while(1) für die Endlosschleife benutzt. Das
for(;;) kannte ich bisher nicht. Insofern hat der Thread ja doch was
gebracht und ich habe was dazu gelernt. Ebenso kannte ich W.S.'s goto
Lösung nicht u.a. auch aus dem Grund goto nur zu verwenden wenn es
wirklich sinnvoll ist. Und wenn ich ganz ehrlich bin, gefällt mir diese
goto Lösung immer besser, auch wenn sie rückwärts springt. Aber sie
erzeugt in dem Fall durchaus verständlichen Code , der nicht weniger
schlecht als while(1) ist und seinen Zweck erfüllt.
Das ist jedenfalls meine (abschließende) Meinung dazu. Es steht
natürlich jedem frei das anders zu sehen und zu handhaben. Da ich das µC
Geschäft lediglich privat betreibe muß ich mich keinen Dogmen
unterwerfen und bin froh darüber.
Zeno
Zeno schrieb:> Mark B. schrieb:>> Mit solchen Dummköpfen mag ich nicht länger diskutieren. Ich bin raus.>> Wenn es keine Argumente mehr hat dann Kopf in den Sand und beleidigt> sein. Aber in diesem Fall ist das gut so.
Ich habe wiederholt nach Beispielen gefragt, die die Aussage "GOTO kann
richtig gut sein" untermauern. Niemand war dazu in der Lage, ein solches
konkretes Beispiel zu liefern.
Ich bleibe dabei: Die meisten Verwender von goto verwenden es deshalb,
weil sie nicht verstanden haben wie man Code geschickt auf möglichst
kleine Funktionen aufteilt. Sie machen zu große Funktionen und springen
dann innerhalb einer solchen fröhlich hin und her, anstatt die
eigentliche Ursache für das "Springen-müssen" abzustellen.
Und ja, ich akzepziere es wenn mir jemand das Gegenteil beweist. Dann
aber bitte nicht einfach nur behaupten, sondern auch tatsächlich
liefern. Ein Verweis auf 384.576 Verwendungen von goto beweist gar
nichts. Ich kann Dir zehn Milliarden Zeilen schlechten Code zeigen,
schlechten Code mit goto, schlechten Code ohne goto, schlechten Code von
Anfängern, schlechten Code von Leuten die seit Jahren programmieren. Was
beweist das? Genau: Nichts.
Zeig mir:
-GUTEN Code mit goto,
-der durch Refactoring nicht mehr besser wird,
-der anerkannte Regeln des Software-Designs befolgt, so wie man sie in
guter Literatur zu dem Thema findet.
Dann bin ich überzeugt.
Und nun gehe hin, und kaufe Dir zum ersten Mal in Deinem Leben ein Buch
über Software-Design. Arbeite es durch, und Du wirst danach ein besserer
Entwickler sein. Versprochen.
Mark B. schrieb:> -der anerkannte Regeln des Software-Designs befolgt, so wie man sie in> guter Literatur zu dem Thema findet.
Da die anerkannten Regeln gemeinhin goto verbieten... ;-)
Ich finds praktisch. Und ich benutze es auch ab und zu, insbesonders um
vorzeitig aus Funktionen mit Fehlercode auszusteigen (die Alternative
wären entweder mehrere verteilte returns (das hasse ich wirklich) oder
aufwändigere Konstrukte, die gar keinen Sinn machen, sondern nur dazu
dienen, dass einfache goto zu vermeiden.
Ja, es geht ohne. Besser, übersichtlicher oder sicherer wird es deshalb
nicht automatisch.
Hallo A.K.
A. K. schrieb:> Mark B. schrieb:>> -der anerkannte Regeln des Software-Designs befolgt, so wie man sie in>> guter Literatur zu dem Thema findet.>> Da die anerkannten Regeln gemeinhin goto verbieten... ;-)
du hast eine Smiley dran, trotzdem noch mal zur Klarstellung:
Tun sie nicht. Der einzige Beleg dazu, der von den Verpönern bisher
geliefert wurde war MISCRA-C:2012 und ein heftiger Schuss in den Ofen.
Denn gerade in MISRA-C ist das Goto Verbot von "mandatory" auf
"advisory" abgestuft worden und es sind sogar neu Hinweise eingeführt
worden, wie ein gutes Goto auszusehen hat.
vlg
Timm
Programmierer schrieb:> Nochmals. Wer etwas sagt, oder wieviele etwas sagen, spielt schlichtweg> keine Rolle.
vielleicht solltest Du aber lieber beim Programmieren bleiben und dich
nicht auf ungewohntes Terrain begeben?
> Plakatives Beispiel: Wieviele Deutsche sind der Meinung, Spinat enthalte> besonders viel Eisen? Wie oft hat man schon gehört, Eskimos hätten> deutlich mehr Wörter für Schnee als Europäer?
Die Autoren der genannten Software haben sich nicht nur an die
Projekt-Guidelines gehalten, sondern sind auch keine Lieschen Müller.
Wenn schon, dann müsste Dein Vergleich lauten: Wieviele Chemiker,
Biologen und Ökotrophologen sind der Meinung, Spinat enthalte besonders
viel Eisen und können diese Meinung unwidersprochen von ausgewiesenen
Experten über Jahrzehnte deklamieren.
Das sieht dann schon anders aus. Was Du da gemacht hast, war nicht
plakativ, sondern angewandter Rabulismus.
Aber Du gehörst sicher zu den Leuten, die stehen bleiben, wenn 6 Leute
vom Kampfmittelräumdienst aus der Absperrung nebenan gesprintet kommen.
> Anderes Beispiel. 2+3 = 5. Daraus kannst Du aber nicht schließen, dass> jede 5 dieser Welt die Summe aus 2+3 ist. Eine 5 kann auch die Summe aus> 1+4 sein.>> Was Du machst, ist ein ganz banaler Argumentationsfehler. Aus "B folgt> aus A" kann man eben gerade nicht schließen, "A folgt aus B".
Ei, das haben wir uns aber schön an den Haaren herbeigezogen. Was
bitteschön hat ein falscher Modus tollens mit dem Gewicht von
Autoritätsargumenten zu tun? Nicht jeder Unsinn ist mit allem verwandt,
was Du für Unsinn hältst.
Autoritätsargumente sind nicht trivial wahr, sondern Gegenstand von
Abwägungen, sie sind aber weder defekt noch per se falsch.
Aber: Drehen wir den Spieß doch um? Möge doch bitte einer der Verpöner
ein großes Open Source Projekt, geschrieben in C, nennen, das kein Goto
enthält?
Oder zumindest endlich mal eine etablierte und verbreitete Richtlinie,
die Goto untersagt.
Vlg
Timm
Timm R. schrieb:> Aber: Drehen wir den Spieß doch um? Möge doch bitte einer der Verpöner> ein großes Open Source Projekt, geschrieben in C, nennen, das kein Goto> enthält?
Hm. Ein großes Projekt, geschrieben in C, mit gutem Software-Design, wo
man bei einem Code Review nicht ständig "What the fuck?" rufen würde.
Hat es so etwas jemals gegeben?
http://www.osnews.com/story/19266/WTFs_m
Mark B. schrieb:> Und nun gehe hin, und kaufe Dir zum ersten Mal in Deinem Leben ein Buch> über Software-Design. Arbeite es durch, und Du wirst danach ein besserer> Entwickler sein. Versprochen.
Du kannst es nicht lassen. Lebe weiter in Deiner Welt mit Deinem
Fanatismus.
Gute Softwareentwickler kennen keine Dogmen, sondern lösen das Problem
und wählen hierfür das Werkzeug/Programmiersprache mit dem/der sich die
Aufgabe am besten lösen läßt. Ein guter Softwareentwickler wird auch den
Sprachumfang einer Programmiersprache ausnutzen und die Sprachelemente
wählen mit denen das Problem am effizientesten gelöst werden. Er kennt
halt keine Dogmen und wird z.B. auch ein goto einsetzen wenn dies Sinn
macht und zu effizienten und gut lesbaren Code beiträgt. Er wird
hingegen ein goto nicht einsetzen, wenn es eine andere gleichwertige
oder bessere Lösung gibt.
Letztendlich ist entscheidend, daß mit der Software das Problem gelöst
wird und diese zuverlässig und stabil funktioniert. Mir als Anwender ist
es völlig wurscht wie die Software die gewünschte Funktionalität
erreicht und ob der Programmierer hierzu goto eingesetzt. Wenn die
Funktionalität vorhanden ist und SW stabil läuft, dann hat sie für mich
eine hohe Qualität.
Mark B. schrieb:> Hm. Ein großes Projekt, geschrieben in C, mit gutem Software-Design, wo> man bei einem Code Review nicht ständig "What the fuck?" rufen würde.> Hat es so etwas jemals gegeben?
Wahrscheinlich nur, wenn diese Software von Herrn Mark Brandis
geschrieben wurde.
Gerade in Deinem letzten Post hast Du wieder einmal bewiesen wie
arrogant Du bist. Alle anderen scheinen ja nach Deinem Verständnis nur
Deppen und Volltrottel zu sein.
Da gibt es nur ein Fazit : Hochmut kommt vor dem Fall.
Zeno
PS: Die Frage ist wie viele große Projekte mit qualitativ hervorragenden
Code hast Du denn schon auf die Beine gestellt? Behaupten kann jeder
viel.
Unabhängig vom ästhetischen Befinden ob "goto's" gut oder schlecht sind,
gibt es vielleicht ein Argument gegen "goto":
Die MISRA-Regeln verbieten es.
( Ich kann leider nur auf die Wikipedia verweisen
- goto soll nicht verwendet werden[6]
MISRA 1998, Regel 56 und MISRA 2004, Regel 10.4
)
Falls man also einmal den Wunsch haben sollte, in der
Automotive-Industrie zu arbeiten, muss man wohl auf das "goto"
verzichten.
chris_ schrieb:> Die MISRA-Regeln verbieten es.
Nicht ganz. Sie empfiehlt nur goto nicht zu verwenden, sie verbietet die
Verwendung aber nicht. Rule 15 behandelt die Verwendung von goto ;)
>Sie empfiehlt nur goto nicht zu verwenden, sie verbietet die>Verwendung aber nicht
Gibt es eigentlich irgendwo im Netz ein Dokument, wo man die MISRA
Regeln einsehen kann?
chris_ schrieb:>>Sie empfiehlt nur goto nicht zu verwenden, sie verbietet die>>Verwendung aber nicht>> Gibt es eigentlich irgendwo im Netz ein Dokument, wo man die MISRA> Regeln einsehen kann?
Google ist dein Freund:
http://archive.redlizards.com/docs/misrac2012-datasheet.pdf
Das wäre aber jetzt auch nicht so schwer gewesen selbst zu finden.
Zeno schrieb:> Gute Softwareentwickler kennen keine Dogmen
Selbstverständlich gibt es Regeln, die man als Programmierer zu
akzeptieren hat. Exakt das unterscheidet einen guten Entwickler von
einem schlechten: Der Gute ist in der Lage, sich an sinnvolle(!) Regeln
zu halten. Er weiß, dass das Ergebnis seiner Arbeit dadurch besser wird.
Der Schlechte programmiert frei Schnauze wie immer er Bock hat, und
produziert dadurch Bockmist. Been there, done that.
Wenn Du eine bestimmte Qualität erreichen willst, ganz besonders wenn
ein Team am Projekt arbeitet und nicht ein Einzelner, dann musst Du
zwingend Regeln aufstellen. Sonst hast Du Wildwuchs. Jeder Programmierer
im Projekt macht dann was er will, und entsprechend beschissen ist
hinterher die Qualität und die Wartbarkeit des Codes.
> Mark B. schrieb:>> Hm. Ein großes Projekt, geschrieben in C, mit gutem Software-Design, wo>> man bei einem Code Review nicht ständig "What the fuck?" rufen würde.>> Hat es so etwas jemals gegeben?> Gerade in Deinem letzten Post hast Du wieder einmal bewiesen wie> arrogant Du bist. Alle anderen scheinen ja nach Deinem Verständnis nur> Deppen und Volltrottel zu sein.
Wer behauptet, dass C gut geeignet für große und komplexe SW-Projekte
sei, der dokumentiert damit dass er nicht viel Ahnung von Software hat.
Die Sprache C war schlicht und ergreifend nie für große, hochkomplexe
SW-Projekte entworfen worden, wie wir sie heute haben. Solche Projekte
mit vielen Millionen Lines Of Code gab es damals, Ende der 60er Anfang
der 70er Jahre, schlicht und ergreifend noch gar nicht.
Entsprechend schlecht ist C für solche Projekte ausgestattet. Das fängt
bei den läppischen Mechanismen für die Fehlerbehandlung an, und hört bei
der sehr zu wünschen übrig lassenden C-Standardbibliothek nicht auf.
Schau Dir Sprachen wie Java, Python und Scala an. Was man da mit wenigen
Zeilen fehlerfrei hinschreiben kann, dafür braucht man in C schon einen
kleinen Urwald an Code. Viel mehr Code nötig, um im Endeffekt das
Gleiche zu tun --> Größeres Fehlerpotenzial.
Niemand hält es heute noch für eine gute Idee, ein großes und komplexes
SW-Projekt in einer Sprache durchzuführen, die den Entwickler so
herzlich wenig dabei unterstützt wie C es eben tut. Außer Dir
vielleicht(?).
C hat seine Berechtigung, wenn man hardwarenah entwickeln will und/oder
eine sehr hohe Ausführungsgeschwindigkeit braucht. Aber selbst dann ist
C++ oftmals die bessere Wahl. Leider kennen viele Programmierer nur ein
Werkzeug, und "if you only have a hammer, then every problem looks like
a nail".
> PS: Die Frage ist wie viele große Projekte mit qualitativ hervorragenden> Code hast Du denn schon auf die Beine gestellt? Behaupten kann jeder> viel.
Ich schreibe seit Jahren Code, der sicherheitstechnisch zertifiziert
wird, vom TÜV und anderen Firmen einem Audit unterzogen wird und vom
Eisenbahnbundesamt abgenommen werden muss. Ansonsten darf das
Schienenfahrzeug mit dem entsprechenden Software-Stand eben nicht fahren
und der Kunde springt uns ins Gesicht. Noch Fragen?
>Die Sprache C war schlicht und ergreifend nie für große, hochkomplexe>SW-Projekte entworfen worden,
hinsichtl. goto ist das Totaler Blödsinn!
Das betr. goto sind prinzipielle Dinge, die rein gar nichts mit einer
speziellen Programmiersprache zu tun haben. Das hast du nicht kapiert.
Und den o.g. Ausschluss kannst du auch nicht machen (und für dieses
Beispiel auch nichts besseres bringen ohne goto).
Offensichtlich redest du nur nach, was man dir vorgibt, wie auch
>Selbstverständlich gibt es Regeln, die man als Programmierer zu>akzeptieren hat.
zeigt.
-------------------------------------
Und nochmal ganz allgemein:
Das Problem besteht (u.a), sobald von MEHREREN Stellen aus die Gleiche
Behandlung (oder gleiche Codeteile) ausgeführt werden sollen.
Bitte kann man jemand diesen Titel im ersten Beitrag ändern damit der
eklatante Rechtschreibfehler behoben wird.
Wenn der Thread nur 1 Tag aktiv wäre hätte man das überleben können,
aber so wird man in der Forumsübersicht jeden Tag mit der Augenkrebs und
Übelkeit verursachenden defekten Rechtscheibung des "verpönnt"
konfrontiert, mir rollen sich da die Fussnägel auf und stülpt sich der
Magen um.
MCUA schrieb:> Das betr. goto sind prinzipielle Dinge, die rein gar nichts mit einer> speziellen Programmiersprache zu tun haben. Das hast du nicht kapiert.
Das stimmt so nicht ganz. In C++ zum Beispiel habe ich ganz andere
Mechanismen zur Fehlerbehandlung, eben die Exceptions. Wenn man ein
solches Sprachmittel verwenden kann, gibt es nun wirklich keinen Grund
mehr stattdessen goto vorzuziehen.
Java kennt kein goto.
Python kennt kein goto.
Warum haben diese Sprachen keine unbedingten Sprünge? Weil man sie nicht
braucht - allerspätestens dann, wenn man bessere Sprachmittel zur
Verfügung hat. Und auch vorher schon kann man ohne auskommen, wenn man
will.
> Und den o.g. Ausschluss kannst du auch nicht machen (und für dieses> Beispiel auch nichts besseres bringen ohne goto).> Offensichtlich redest du nur nach, was man dir vorgibt, wie auch>>Selbstverständlich gibt es Regeln, die man als Programmierer zu>>akzeptieren hat.> zeigt.>> -------------------------------------> Und nochmal ganz allgemein:> Das Problem besteht (u.a), sobald von MEHREREN Stellen aus die Gleiche> Behandlung (oder gleiche Codeteile) ausgeführt werden sollen.
Gleiche Codeteile steckt man üblicherweise in eine eigene Funktion. Die
kann man aufrufen, von wo immer aus man will. Welchen Vorteil bringt
goto gegenüber dem Aufruf einer eigenständigen Funktion?
Yalu X. schrieb:> Michael B. schrieb:>> Bitte kann man jemand diesen Titel im ersten Beitrag ändern damit der>> eklatante Rechtschreibfehler behoben wird.>> Hab's geändert.
Danke, der Krebs ist weg.
Hier mal der Ausschnitt aus den MISRA Regeln, weil sie eine sinnhafte
Anwendung des GOTO zu beschreiben:
aus: http://archive.redlizards.com/docs/misrac2012-datasheet.pdf
Rule-15.1
The goto statement should
not be used
Advisory
Decidable
MISRAC2012-Rule-15.1
:
Uses of goto.
Rule-15.2
The goto statement shall
jump to a label declared later
in the same function
Required
Decidable
MISRAC2012-Rule-15.2
:
Backwards goto's
Rule-15.3
Any label referenced by a
goto statement shall be
declared in the same block,
or in any block enclosing the
goto statement
Required
Decidable
MISRAC2012-Rule-15.3
:
Goto's into a nested block
Rule-15.4
There should be no more
than one break or goto
statement used to terminate
any iteration statement
Advisory
Decidable
MISRAC2012-Rule-15.4
:
Two or more break or goto
statements in a loop
Rule-15.5
A function should have a
single point of exit at the end
Advisory
Decidable
MISRAC2012-Rule-15.5
:
Functions with multiple
points of exit
>M. Köhler (sylaina)>Das wäre aber jetzt auch nicht so schwer gewesen selbst zu finden.
Diese Art Kommentar kannst Du Dir grundsätzlich sparen.
steffen schrieb:> Diese Art Kommentar kannst Du Dir grundsätzlich sparen.
Da ich mir das sparen kann und nicht muss mach ich von meiner
Möglichkeit gebrauch mir solch einen Kommentar nicht zu sparen. Wenn
jemanden so etwas interessiert, ist es wirklich zuviel verlangt dass
dieser dann zumindest mal MISRA in eine Suchmaschine seiner Wahl
eingibt?
Mark B. schrieb:> Wer behauptet, dass C gut geeignet für große und komplexe SW-Projekte> sei, der dokumentiert damit dass er nicht viel Ahnung von Software hat.
Ich habe nur einen Teil Deines Postes zitiert, um quasi einen Verweis zu
haben, und nicht behauptet das C für große Projekte gut geeignet ich. Im
Gegenteil ich persönlich meide C wo es nur geht, da ich von dieser
Sprache nicht überzeugt bin. C öffnet Tür und Tor um schlecht lesbaren
und kompromitierbaren Code zu schreiben. Es würde jetzt zu weit führen
alle Features in C aufzuzählen die mir nicht gefallen, das ist auch
nicht Thema des Threads und es ist meine ganz persönliche Meinung. Im
Umkehrschluß bedeutet das jetzt nicht das alle C-Programmierer Deppen
sind die keine Ahnung von Coden haben, wie die Vielzahl (großer und
kleiner) Projekte beweist. Welche Programmiersprache man benutzt hängt
auch etwas davon ab womit man "groß" geworden ist bzw. sein erstes
größeres Projekt verwirklicht hat.
Ich hatte es schon geschrieben: Zum Schluß zählt das Endprodukt und wie
der Programmierer dahin gekommen ist, interessiert den Anwender nicht.
C verwende ich nur zur Programmierung von µC's, weil es hierfür nichts
anderes gibt, zumindest keinen guten Pascalcompiler.
Und um es gleich vorweg zu nehmen ich bin auch kein Freund von C++ und
C#. Beide basieren auf C und haben letztendlich alle Unzulänglichkeiten
von C mitgenommen. Allein die Anzahl der Zuweisungsoperatoren in C++ ist
eine Zumutung (=, -> und dann noch die Umleitungsoperatoren) sprechen
für sich, um nur mal ein Beispiel zu nennen. Alles nur irgendwie
zusammen gefrickelt. In Pascal beispielsweise gibt es nur einen einzigen
nämlich := und der gilt für alle Zuweisungen. Oder man nehme HP/HT-Basic
her, da heißt der Zuweisungsoperator -> und fertig.
Ich will jetzt die Qualität der Programmiersprache nicht am
Zuweisungsoperator fest machen, aber das ist mir jetzt gerade
eingefallen als ein Feature welches mir nicht gefällt.
C# ist auch nicht besser aber ich muß es für ein große Projekt benutzen
weil mein Arbeitgeber das wünscht.
Wie gesagt alles meine persönliche Meinung. Es darf jeder anders sehen
und jeder soll die Programmierwerkzeuge benutzen von denen er meint, daß
er damit seine Aufgaben am besten erfüllen kann und gut ist.
Jeglicher Fanatismus ist da fehl am Platze.
Zeno
M. K. schrieb:> chris_ schrieb:>>>Sie empfiehlt nur goto nicht zu verwenden, sie verbietet die>>>Verwendung aber nicht>>>> Gibt es eigentlich irgendwo im Netz ein Dokument, wo man die MISRA>> Regeln einsehen kann?>> Google ist dein Freund:> http://archive.redlizards.com/docs/misrac2012-datasheet.pdf>> Das wäre aber jetzt auch nicht so schwer gewesen selbst zu finden.
Das Datasheet ist aber leider nur die halbe Wahrheit, es listet nur auf
ohne Erläuterungen, der gesamte MISRA-C:2012 Standard hat 236 Seiten und
ist legal nur bei MISRA zu kaufen (Kostet aber nicht die Welt: GBP 15 +
VAT). Wie jemand schon gesagt hat (um mich genüsslich richtigzustellen,
hatte am WoE leider nicht den Text des Standards zur Verfügung und nur
aus dem Gedächtnis zitiert), besagt Rule 15.1 bei MISRA "The goto
statement should not be used" und ist eine sog. Advisory-Regel. Jetzt
ist das aber nicht bloß als eine Empfehlung abzukanzeln, sondern es
heißt bei MISRA (sinngemäß übersetzt, Quelle: MISRA-C:2012, Kap. 6.2.3,
S.13):
Advisory guidelines sind Empfehlungen. Das bedeutet aber nicht, dass
diese Punkte ignoriert werden können, sondern soweit als sinnvoll
möglich zu befolegen sind. Der Prozess für formale Abweichungen muss
nicht eingehalten werden, aber das Nichtbefolgen ist zu dokumentieren.
Eine Organisation kann für sich entscheiden, advisory guidelines als
mandatory zu behandeln.
Außerdem erlaubt MISRC-C goto nur unter den folgenden Bedingungen:
- nur Vorwärtssprünge sind erlaubt (Rule 15.2)
- nur Sprünge im lokalen Block sind erlaubt (Rule 15.3)
- maximal ein goto (oder break) darf eine Schleife beenden (Rule 15.4)
Das schließt meinem Dafürhalten nach Schleifenbildung mit goto definitiv
aus.
Grüsse
Herby
Herbert P. schrieb:> Das Datasheet ist aber leider nur die halbe Wahrheit...
Oh, dagegen habe ich auch nichts zu sage. Ich wollte damit nur drauf
hinweisen, dass Aussagen wie diese hier:
chris_ schrieb:> Die MISRA-Regeln verbieten es.
schlicht falsch sind.
Zum eigentlichen Thema kann ich nur sagen, dass auch ich es gelehrt
bekommen habe goto zu vermeiden. Ich bin in C aber bisher auch noch nie
in die Verlegenheit gekommen, dass ich ein goto gebraucht hätte. Es lies
sich immer vermeiden bei den Programmen, die ich schrieb. Weiter oben
jedoch, das USB-Beispiel, ist, finde ich, mit goto ein stückweit
lesbarer als mit den ineinander verschachtelter Schleifen. Was von
beiden Varianten nun aber wirklich der allgemein bessere Code ist vermag
ich nicht zu sagen.
@M. Köhler (sylaina)
>Zum eigentlichen Thema kann ich nur sagen, dass auch ich es gelehrt>bekommen habe goto zu vermeiden.
Me too. Beim Umstieg von BASIC auf Pascal in der Schule war das nicht
vorhandene bzw. nicht erlaubte GoTo erstmal ein Schock.
Meine Reaktion "Geht doch gar nicht!!!".
Und es ging doch, und das sogar problemlos.
> Ich bin in C aber bisher auch noch nie>in die Verlegenheit gekommen, dass ich ein goto gebraucht hätte. Es lies>sich immer vermeiden bei den Programmen, die ich schrieb.
Me too, wenn gleich ich nicht der große Programierer bin. Meine
Programme spielen am unteren Ende der Skala, was Umfang und Komplexität
angeht.
> Weiter oben>jedoch, das USB-Beispiel, ist, finde ich, mit goto ein stückweit>lesbarer als mit den ineinander verschachtelter Schleifen.
Du vermischt was. Im USB-Beispiel war es ein Switch, die Schleifen waren
der TCP Ausschnitt aus dem RTOS.
>Was von>beiden Varianten nun aber wirklich der allgemein bessere Code ist vermag>ich nicht zu sagen.
Das RTOS-Beispiel kommt ohe Goto spielend aus, ist sehr lesbar und mit
der Erweiterung auf eine ENDLICHE Anzahl von Suchvorgängen sogar
wasserdicht.
Das USB-Beipiel gewinnnt durch goto nur minimal an Lesbarkeit, eine
Funktion oder das Setzen eines Flags an der Stelle wären ebenso OK und
goto-frei ;-)