Forum: Mikrocontroller und Digitale Elektronik goto verpönt - was dann nehmen?


von Paul (Gast)


Lesenswert?

Hallo
in meinen Programmen nehme ich sehr häufig
1
void aufruf()
2
{ 
3
... tu was
4
}
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

: Bearbeitet durch Moderator
von Peter II (Gast)


Lesenswert?

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.

von Kaj (Gast)


Lesenswert?

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.

von Stefan F. (Gast)


Lesenswert?

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.

von Paul H. (powl)


Lesenswert?

Ein guter Paul schaut lieber nach bevor er es gleich zwei mal falsch 
macht ;-)

http://www.duden.de/rechtschreibung/verpoent

von Jörg M. (derlang)


Lesenswert?

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

von Dirk B. (dirkb2)


Lesenswert?

Paul schrieb:
> Was nutz ihr bei solchen Sachen?

for, while, do-while, if-else, return, break

von Stefan F. (Gast)


Lesenswert?

> 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.

von Peter II (Gast)


Lesenswert?

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.

von Dirk B. (dirkb2)


Lesenswert?

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)

von Stefan F. (Gast)


Lesenswert?

µ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.

von Paul (Gast)


Lesenswert?

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

von Matze (Gast)


Lesenswert?

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?

von Stefan F. (Gast)


Lesenswert?

> 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.

von Bellis Perennis (Gast)


Lesenswert?

>goto verpönnt - was dann nehmen?

Lieber GITTI als GOTO.

von Sebastian (Gast)


Lesenswert?

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

von Clemens M. (panko)


Lesenswert?

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.

von Heinz L. (ducttape)


Lesenswert?

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.

von MaWin (Gast)


Lesenswert?

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.

von Thomas E. (picalic)


Lesenswert?

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.

von Jörg M. (derlang)


Lesenswert?

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.

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

> 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.

von Joachim B. (jar)


Lesenswert?

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?

von Peter II (Gast)


Lesenswert?

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/

von Heinz L. (ducttape)


Lesenswert?

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.

von Matze (Gast)


Lesenswert?

Peter II schrieb:
> 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/

Wird auch im Kapitel 7 des "Linux kernel coding style" so beschrieben:

https://www.kernel.org/doc/Documentation/CodingStyle

von Jan K. (madengineer)


Lesenswert?

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?

von Heinz L. (ducttape)


Lesenswert?

Oder einfacher der erste Code ohne Goto:
1
#define NUMBER_OF_VARS 4
2
#define A_OK 1
3
#define ERROR 0
4
static char* a[NUMBER_OF_VARS];
5
6
int do_initialize()
7
{
8
   for (i=0;i<NUMBER_OF_VARS;i++)
9
   {
10
      if (!(a[i]=malloc(10))
11
        return ERROR;
12
   }
13
   return A_OK;
14
}
15
16
void do_cleanup()
17
{
18
  int i=0;
19
  while (a[i])
20
    free (a[i++]);
21
}
22
23
int main()
24
{
25
  if (do_initialize() == ERROR)
26
    do_cleanup();
27
}

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.

: Bearbeitet durch User
von MaWin (Gast)


Lesenswert?

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 ?

von Clemens M. (panko)


Lesenswert?

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.

von Joachim B. (jar)


Lesenswert?

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.

: Bearbeitet durch User
von Mark B. (markbrandis)


Lesenswert?

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. ;-)

von foobar (Gast)


Lesenswert?

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.

von Third E. (third-eye)


Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

Eine Renaissance des Goto? OMG!

Rein syntaktisch ist Goto in C vollkommen überflüssig. Praktisch ist es 
nur in EXTREM wenigen Situationen gerechtfertigt.

von Joachim B. (jar)


Lesenswert?

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.

von Stefan F. (Gast)


Lesenswert?

> 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.

von TestX (Gast)


Lesenswert?

@third-eye

dafür gibt es inline funktionen...schon ist der overhead raus

von Peter II (Gast)


Lesenswert?

Stefan U. schrieb:
> Den Ressourcenstackabbau  implementiere ich (in allen Sprachen) anders.

und in Sprachen ohne Exception/Finaly?

von MaWin (Gast)


Lesenswert?

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).

von Diodenes (Gast)


Lesenswert?

Paul schrieb:

> goto verpönnt - was dann nehmen?

> Im Netz wird da von gesprochen, das es verpöönt ist nichrr genutzt
> werden soll.
> Was nutz ihr bei solchen Sachen?

COME FROM

http://catb.org/esr/intercal/ick.htm#COME-FROM-and-NEXT-FROM
https://de.wikipedia.org/wiki/INTERCAL

;-)

von nicht"Gast" (Gast)


Lesenswert?

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.

von Jay (Gast)


Lesenswert?

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?

von Doh! (Gast)


Lesenswert?

Pro:
https://www.cs.sjsu.edu/~mak/CS185C/KnuthStructuredProgrammingGoTo.pdf
Contra:
https://www.cs.utexas.edu/users/EWD/ewd02xx/EWD215.PDF

Wenn zwei Turing Award Gewinner sich hier nicht einig waren, was besser 
ist (wohl weil jeder einen anderen Fokus hatte) bezweifle ich, dass man 
die Lösung hier erarbeiten kann.

von informatik student (Gast)


Lesenswert?

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.

von Heinz L. (ducttape)


Lesenswert?

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?

von Peter II (Gast)


Lesenswert?

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.

von Stefan F. (Gast)


Lesenswert?

> 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.

von Doh! (Gast)


Lesenswert?

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?

von Jodel (Gast)


Lesenswert?

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.

von MaWin (Gast)


Lesenswert?

Stefan U. schrieb:
> sondern über das Aufräumen von Ressourcen, die zum teil gar
> nicht belegt wurden

Daher schreibt man in C
1
File input=fopen("filename1");
2
if(input)
3
{
4
    File output=fopen("filename2");
5
    if(output)
6
    {
7
        Converter converter=NewConverter(params);
8
        if(converter)
9
        {
10
            while (input.hasMore())
11
            {
12
                line=input.readLine();
13
                output.writeLine(converter.convert(line));
14
            } 
15
            converter.close();
16
        }
17
        output.close();
18
    }
19
    input.close();
20
}
und weil wir in C++ Exceptions haben
1
try
2
{
3
    File input=new File("filename1");
4
    try
5
    {
6
        File output=new File("filename2");
7
        try
8
        {
9
            Converter converter=new Converter(params);
10
            try
11
            {
12
                while (input.hasMore())
13
                {
14
                    line=input.readLine();
15
                    output.writeLine(converter.convert(line));
16
                }
17
            }
18
            catch 
19
            {
20
                // jeweils geeignetes Errorhandling
21
            }
22
        }
23
    }
24
    // weil deallozierte Klassen sich von selbst (.close) aufzuräumen haben
25
}

von Sebastian V. (sebi_s)


Lesenswert?

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.

von corruptmemory (Gast)


Lesenswert?

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) ?

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

$ 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

von Bellis Perennis (Gast)


Lesenswert?

Μα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.

von Dussel (Gast)


Lesenswert?

Μα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'.

von Mark B. (markbrandis)


Lesenswert?

Μα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.

von Mark B. (markbrandis)


Lesenswert?

Dussel schrieb:
> Goto hat ja seine Berechtigung, nur eben absolut nicht für Anfänger

Vollkommen richtig.

von Peter II (Gast)


Lesenswert?

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;"

von Peter II (Gast)


Lesenswert?

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.

von Heinz L. (ducttape)


Lesenswert?

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.

von danvet (Gast)


Lesenswert?

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]

von Mark B. (markbrandis)


Lesenswert?

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.

: Bearbeitet durch User
von Jens G. (jensig)


Lesenswert?

@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"?

von Walter S. (avatar)


Lesenswert?

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

: Bearbeitet durch User
von Jens G. (jensig)


Lesenswert?

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 ...

von Joachim B. (jar)


Lesenswert?

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?
1
  //Ausgabe der Zeichen
2
  for(;;)
3
  {  by = pgm_read_byte(Buffer++);
4
    if(by==0) break; // end of format string
5
    if (by == '%')
6
    {  by = pgm_read_byte(Buffer++);
7
      if (isdigit(by)>0)
8
      {  str_null_buffer[0] = by;
9
        str_null_buffer[1] = '\0';
10
        move = atoi(str_null_buffer);
11
              by = pgm_read_byte(Buffer++);
12
      }
13
      if(by=='X')
14
        upp=1;
15
      switch (by)
16
      {  case 's':
17
                ptr = va_arg(ap,char *);
18
          while(*ptr) { usart_write_char(*ptr++); }
19
          break;
20
        case 'b':
21
          Base = 2;
22
          goto ConversionLoop;
23
        case 'c':
24
          //Int to char
25
          format_flag = va_arg(ap,int);
26
          usart_write_char (format_flag++);
27
          break;
28
        case 'i':
29
          Base = 10;
30
          goto ConversionLoop;
31
        case 'o':
32
          Base = 8;
33
          goto ConversionLoop;
34
        case 'x':
35
        case 'X':
36
          Base = 16;
37
          //****************************
38
          ConversionLoop:
39
          //****************************
40
          itoa(va_arg(ap,int),str_buffer,Base);
41
          int b=0;
42
          while (str_buffer[b++] != 0){};
43
          b--;
44
          if (b<move)
45
          {  move -=b;
46
            for (tmp = 0;tmp<move;tmp++)
47
              str_null_buffer[tmp] = '0';
48
            //tmp ++;
49
            str_null_buffer[tmp] = '\0';
50
            strcat(str_null_buffer,str_buffer);
51
            strcpy(str_buffer,str_null_buffer);
52
          }
53
          (!upp) ? usart_write_str(str_buffer) : usart_write_str(strupr(str_buffer));
54
          move =0;
55
          break;
56
      }
57
    }  
58
    else
59
      usart_write_char ( by );  
60
  }

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

@Joachim B. (jar)

>wie gehts elegant ohne goto?

Als erstes mal mit weniger Leerzeilen!

von Joachim B. (jar)


Lesenswert?

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

von Falk B. (falk)


Angehängte Dateien:

Lesenswert?

Etwa so. War echt schwer . . .

von Joachim B. (jar)


Lesenswert?

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.

von Sebastian S. (amateur)


Lesenswert?

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.

von nichtCler (Gast)


Lesenswert?

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?

von Joachim B. (jar)


Lesenswert?

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.

: Bearbeitet durch User
von Dummbernd (Gast)


Lesenswert?

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.

von nichtCler (Gast)


Lesenswert?

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.

von Sebastian S. (amateur)


Lesenswert?

>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.

von S. R. (svenska)


Lesenswert?

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.

von Harry L. (mysth)


Lesenswert?

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

: Bearbeitet durch User
von Sheeva P. (sheevaplug)


Lesenswert?

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.

von Stefan F. (Gast)


Lesenswert?

> 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.

von Falk B. (falk)


Angehängte Dateien:

Lesenswert?

@ 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.

von W.A. (Gast)


Lesenswert?

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.

von Rolf M. (rmagnus)


Lesenswert?

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?

von W.A. (Gast)


Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

@ 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 ;-)

von Joachim B. (jar)


Lesenswert?

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;
}

von Wegstaben V. (wegstabenverbuchsler)


Lesenswert?

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.

von Wegstaben V. (wegstabenverbuchsler)


Lesenswert?

Joachim B. schrieb:
> 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;
> }

Dafür gibt es Switch-Case Anweisungen. Schonmal ausprobiert?
http://www.c-howto.de/tutorial-verzweigungen-switch-case.html

von W.A. (Gast)


Lesenswert?

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.

von Paul B. (paul_baumann)


Lesenswert?

Wenn es statt "Goto" "HUPF" hieße, würden sich die Leute auch nicht so 
gegen seine Verwendung sträuben.

MfG Paul

von Joachim B. (jar)


Lesenswert?

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;

}

von The D. (thedaz)


Lesenswert?

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).

von nanana (Gast)


Lesenswert?

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?

von Helmut L. (helmi1)


Lesenswert?

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
.
.
..

von Axel S. (a-za-z0-9)


Lesenswert?

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.

von Freddy (Gast)


Lesenswert?

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

von Rolf M. (rmagnus)


Lesenswert?

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?

von Falk B. (falk)


Lesenswert?

@ 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)

von Dussel (Gast)


Lesenswert?

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.

von Rolf M. (rmagnus)


Lesenswert?

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.

von Heinz L. (ducttape)


Lesenswert?

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.

von Joachim B. (jar)


Lesenswert?

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.

von Thomas E. (picalic)


Lesenswert?

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!

von Falk B. (falk)


Lesenswert?

@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.

von Falk B. (falk)


Lesenswert?

@ 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.

von Joachim B. (jar)


Lesenswert?

Falk B. schrieb:
>>Ich selber staune immer wie gut der gcc optimiert mit -0s
>
> Das tut er.

danke Falk!

von Frank B. (f-baer)


Lesenswert?

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:
1
if(z_measurement_g)
2
    {
3
      if(Z1_g.motion_ctrl.mode_active == mode_z_measurement)
4
        goto Z1_measurement;
5
      if(Z2_g.motion_ctrl.mode_active == mode_z_measurement)
6
        goto Z2_measurement;      
7
      if(Z3_g.motion_ctrl.mode_active == mode_z_measurement)
8
        goto Z3_measurement;  
9
      if(Z4_g.motion_ctrl.mode_active == mode_z_measurement)
10
        goto Z4_measurement;  
11
      if(Z5_g.motion_ctrl.mode_active == mode_z_measurement)
12
        goto Z5_measurement;  
13
      if(Z6_g.motion_ctrl.mode_active == mode_z_measurement)
14
        goto Z6_measurement;  
15
      if(Z7_g.motion_ctrl.mode_active == mode_z_measurement)
16
        goto Z7_measurement;  
17
    }
18
    
19
Z1_measurement:
20
    stepper_handle(&Z1_g);    
21
    if(z_measurement_g)
22
      continue;  
23
Z2_measurement:
24
    stepper_handle(&Z2_g);
25
    if(z_measurement_g)    
26
      continue;    
27
Z3_measurement:    
28
    stepper_handle(&Z3_g);
29
    if(z_measurement_g)    
30
      continue;  
31
Z4_measurement:
32
    stepper_handle(&Z4_g);
33
    if(z_measurement_g)    
34
      continue;    
35
Z5_measurement:    
36
    stepper_handle(&Z5_g);
37
    if(z_measurement_g)    
38
      continue;  
39
Z6_measurement:    
40
    stepper_handle(&Z6_g);
41
    if(z_measurement_g)    
42
      continue;  
43
Z7_measurement:    
44
    stepper_handle(&Z7_g);
45
    if(z_measurement_g)    
46
      continue;

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.

von MCUA (Gast)


Lesenswert?

>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

von Thomas (Gast)


Lesenswert?

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

von Oliver S. (oliverso)


Lesenswert?

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

von Joachim B. (jar)


Lesenswert?

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.

: Bearbeitet durch User
von nicht"Gast" (Gast)


Lesenswert?

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.
1
motion allAxes[]{ Z1_g, Z2_g, Z3_g, Z4_g, Z5_gZ6_g, Z7_g };
2
3
if (z_measurement_g) {
4
  motion *priorRankedAxis = findPriorRankedAxis(allAxes,sizeof(allAxes));
5
       if (priorRankedAxis != NULL){
6
    stepper_handle(priorRankedAxis);
7
  }
8
}
9
else{
10
  for (int i = 0; i < sizeof(allAxes); i++) {
11
    stepper_handle(&allAxes[i]);
12
  }
13
}

mit
1
motion* findPriorRankedAxis(motion *allAxes, int count) {
2
  for (int i = 0; i < count; i++) {
3
    if (allAxes[i].motion_ctrl.mode_active) {  
4
      return &allAxes[i];
5
    }
6
  }
7
  return NULL;  
8
}

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.

von Entsetzter (Gast)


Lesenswert?

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:

1
  if (!z_measurement_g || Z1_g.motion_ctrl.mode_active == mode_z_measurement)
2
    stepper_handle(&Z1_g);
3
4
  if (!z_measurement_g || Z2_g.motion_ctrl.mode_active == mode_z_measurement)
5
    stepper_handle(&Z2_g);
6
7
  if (!z_measurement_g || Z3_g.motion_ctrl.mode_active == mode_z_measurement)
8
    stepper_handle(&Z3_g);
9
10
  if (!z_measurement_g || Z4_g.motion_ctrl.mode_active == mode_z_measurement)
11
    stepper_handle(&Z4_g);
12
13
  if (!z_measurement_g || Z5_g.motion_ctrl.mode_active == mode_z_measurement)
14
    stepper_handle(&Z5_g);
15
16
  if (!z_measurement_g || Z6_g.motion_ctrl.mode_active == mode_z_measurement)
17
    stepper_handle(&Z6_g);
18
19
  if (!z_measurement_g || Z7_g.motion_ctrl.mode_active == mode_z_measurement)
20
    stepper_handle(&Z7_g);

Und wenn Du dass noch Z1_g bis Z7_g in ein Array wandelst, verfällt 
dieser GOTO-Continue-Wahnsinn in eine einfache Schleife aus vier Zeilen!

von nicht"Gast" (Gast)


Lesenswert?

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:
1
motion *allAxes[]{ &Z1_g, &Z2_g, &Z3_g, &Z4_g, &Z5_g, &Z6_g, &Z7_g };
2
int axesCount = sizeof(allAxes) / sizeof(*allAxes);
3
4
if (z_measurement_g) {
5
  motion *priorRankedAxis = findPriorRankedAxis(allAxes, axesCount);
6
  if (priorRankedAxis != NULL) {
7
    stepper_handle(priorRankedAxis);
8
  }
9
}
10
else {
11
  for (int i = 0; i < axesCount; i++) {
12
    stepper_handle(allAxes[i]);
13
  }
14
}

mit
1
motion* findPriorRankedAxis(motion **allAxes, int count) {
2
  for (int i = 0; i < count; i++) {
3
    if (allAxes[i]->motion_ctrl.mode_active) {
4
      printf("gefunden %d\n", i);
5
      return allAxes[i];
6
    }
7
  }
8
  return NULL;
9
}

von Paul B. (paul_baumann)


Lesenswert?

nicht"Gast" schrieb:
> Oh je, das war natürlich Blödsinn mit dem Zeiger.

Das hat ja nicht lange gedauert, bis das jemand auf den Zeiger ging

MfG Paul

von W.S. (Gast)


Lesenswert?

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.

von Dussel (Gast)


Lesenswert?

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

von Rüdiger (Gast)


Lesenswert?

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...

von Bernd K. (prof7bit)


Lesenswert?

Rüdiger schrieb:
> Mein Favorit ist ja noch immer:
> while("my guitar gently weeps")

Optimiert er den String weg? Bin jetzt zu faul ums auszuprobieren.

von Rolf M. (rmagnus)


Lesenswert?

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.

von W.S. (Gast)


Lesenswert?

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.

von S. R. (svenska)


Lesenswert?

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. ;-)

von Sheeva P. (sheevaplug)


Lesenswert?

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.

von Thomas E. (picalic)


Lesenswert?

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.

von Josef G. (bome) Benutzerseite


Lesenswert?

W.S. schrieb:
> for (;;;) blabla...;
> while (1) blabla...;

Zum Thema Endlosschleife mit bedingtem break:
Beitrag "Gibt es eine Programmiersprache mit diesem Schleifentyp?"

von Michael S. (rbs_phoenix)


Lesenswert?

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
goto Anfang;

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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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).

: Bearbeitet durch Moderator
von Soul E. (Gast)


Lesenswert?

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.

von Bitwurschtler (Gast)


Lesenswert?

?Sprungtabelle?
https://de.wikipedia.org/wiki/Sprungtabelle

Wer versteht diesen C-Code ohne gotos besser als einen mit?
1
typedef void (*Handler)(void);    /* A pointer to a handler function */
2
3
/* The functions */
4
void func3 (void) { printf( "3\n" ); }
5
void func2 (void) { printf( "2\n" ); }
6
void func1 (void) { printf( "1\n" ); }
7
void func0 (void) { printf( "0\n" ); }
8
9
Handler jump_table[4] = {func0, func1, func2, func3};
10
11
int main (int argc, char **argv) {
12
    int value;
13
14
    /* Convert first argument to 0-3 integer (modulus) */
15
    value = ((atoi(argv[1]) % 4) + 4) % 4;
16
17
    /* Call appropriate function (func0 thru func3) */
18
    jump_table[value]();
19
20
    return 0;
21
}

von Dussel (Gast)


Lesenswert?

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.

von Clemens L. (c_l)


Lesenswert?

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:
1
int main (int argc, char *argv[])
2
{
3
    static const void *jump_table[4] = {&&func0, &&func1, &&func2, &&func3};
4
5
    int value = ((atoi(argv[1]) % 4) + 4) % 4;
6
7
    goto jump_table[value];
8
9
func0:
10
    printf( "0\n" );
11
    return 0;
12
13
func1:
14
    printf( "1\n" );
15
    return 0;
16
17
func2:
18
    printf( "2\n" );
19
    return 0;
20
21
func3:
22
    printf( "3\n" );
23
    return 0;
24
}

Oder vielleicht doch besser switch() ...

von M. K. (sylaina)


Lesenswert?

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...

von MCUA (Gast)


Lesenswert?

Der Controller kennt eh nur JMP und JSR.
aber MCP (wohl als einzigste) nennen das GOTO

von Bitwurschtler (Gast)


Lesenswert?

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.

von kast (Gast)


Lesenswert?

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

von Bitwurschtler (Gast)


Lesenswert?

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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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 …

von Bitwurschtler (Gast)


Lesenswert?

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" "  };-)

von Hugo (Gast)


Lesenswert?

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? ;-)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Hugo (Gast)


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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. ;-)

von Dussel (Gast)


Lesenswert?

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. :-)

von M. K. (sylaina)


Lesenswert?

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.

von Thomas E. (picalic)


Lesenswert?

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.

von Oliver S. (oliverso)


Lesenswert?

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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.
1
% find /sys/ -name \*.c | xargs grep -w goto | wc -l
2
   23976

Selbst, wenn davon 10000 gotos überflüssig wären, blieben immer noch
14000, die es nicht sind.

von W.S. (Gast)


Lesenswert?

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
int main (void)
2
{ // initialisierungen
3
  ....
4
5
  while (1)
6
  { // irgendwelcher Inhalt
7
    ...
8
  }
9
  return 0;
10
}

weil er sonst vom Compiler angepfiffen wird. Selber schon unzählige Male 
erlebt.

Wie also geht's besser? So:
1
int main (void)
2
{ // initialisierungen
3
  ....
4
5
  elleweil:
6
   // irgendwelcher Inhalt
7
    ...
8
  goto elleweil;
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
int blabla (.....)
2
{ int retcode;
3
4
  Aktion1...  // z.B. File öffnen
5
  retcode=1;
6
  if (!Kondition1()) goto raus_hier;
7
 
8
  Aktion2...  // z.B. parsen
9
  retcode=2;
10
  if (!Kondition2()) goto raus_hier;
11
12
  Aktion2...  // z.B. noch ne Datei öffnen
13
  nochmal sowas wie oben
14
15
  retcode=Is_OK;
16
  MachSonstwas...
17
18
raus_hier:
19
  RäumeAuf, SchließeAb...
20
  return RetCode;
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.

von Falk B. (falk)


Lesenswert?

@ 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.

von W.S. (Gast)


Lesenswert?

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.

von Dussel (Gast)


Lesenswert?

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.

von Bernd K. (prof7bit)


Lesenswert?

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

: Bearbeitet durch Moderator
von Rolf M. (rmagnus)


Lesenswert?

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?

von nichtCler (Gast)


Lesenswert?

In C gibt es goto weil das C-nahe Assembler auch nicht ohne equivalentes 
auskommt :)

von M. K. (sylaina)


Lesenswert?

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

von W.S. (Gast)


Lesenswert?

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.

von Dussel (Gast)


Lesenswert?

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.

von Fpgakuechle K. (Gast)


Lesenswert?

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.

von M. K. (sylaina)


Lesenswert?

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.)

von Dussel (Gast)


Lesenswert?

M. K. schrieb:
> Dass man sich darum kümmert die Warnung zu beseitigen.
Und den Fehler beseitigt man nicht? :D

von M. K. (sylaina)


Lesenswert?

Bei dir laufen Programme obwohl der Compiler Fehler geworfen hat? 
Beeindruckend, meiner macht da erst gar kein Hexfile draus. ;)

von Dussel (Gast)


Lesenswert?

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.)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von M. K. (sylaina)


Lesenswert?

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

von Bernd K. (prof7bit)


Lesenswert?

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.

von Zeno (Gast)


Lesenswert?

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
int main(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

von Oliver S. (oliverso)


Lesenswert?

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

von asdf (Gast)


Lesenswert?

Zeno schrieb:
> ein genauso unsägliches
> Konstrukt wie for(;;;)

Vor allem deshalb, weil es das gar nicht gibt :-)

Lies mal nach und vergleiche:
http://www.c-howto.de/tutorial-schleifen-for.html

von Oliver S. (oliverso)


Lesenswert?

Versuch macht kluch...

Und dann mal K&R lesen.

Oliver

von asdf (Gast)


Lesenswert?

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?

von Bernd K. (prof7bit)


Lesenswert?

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.

von Helmut L. (helmi1)


Lesenswert?

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

von Rolf M. (rmagnus)


Lesenswert?

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.

von Bernd K. (prof7bit)


Lesenswert?

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.

: Bearbeitet durch User
von Rolf M. (rmagnus)


Lesenswert?

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.

: Bearbeitet durch User
von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

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?

von M. K. (sylaina)


Lesenswert?

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.

von Dussel (Gast)


Lesenswert?

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.

von Dussel (Gast)


Lesenswert?

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.

von Rolf M. (rmagnus)


Lesenswert?

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.

von Zeno (Gast)


Lesenswert?

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

von Hugo (Gast)


Lesenswert?

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 :-)

von Zeno (Gast)


Lesenswert?

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
void main(void)
2
{
3
....
4
}

Dabei ist es egal ob man als Endlosschleife while(1), for(;;) oder 
W.S.'s goto nimmt.

Zeno

von Zeno (Gast)


Lesenswert?

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

von Zeno (Gast)


Lesenswert?

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

von Paul B. (paul_baumann)


Lesenswert?

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

von Bernd K. (prof7bit)


Lesenswert?

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
int main (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?

: Bearbeitet durch User
von M. K. (sylaina)


Lesenswert?

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?

von Thomas E. (picalic)


Lesenswert?

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!

von Yalu X. (yalu) (Moderator)


Lesenswert?

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."

von nichtCler (Gast)


Lesenswert?

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.

von Rolf M. (rmagnus)


Lesenswert?

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
void sighandler(int sig)
2
{
3
    sig = sig;
4
    // ...
5
}
oder auch:
1
void sighandler(int sig)
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?

von nichtCler (Gast)


Lesenswert?

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/Warnung
https://de.wikipedia.org/wiki/Hinweis

Ich kenne keinen Compiler der soviel taugt, daß er da einen Unterschied 
macht.

von Michael S. (rbs_phoenix)


Lesenswert?

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.

von Programmierer (Gast)


Lesenswert?

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!

von Mani W. (e-doc)


Lesenswert?

Vielleicht wäre statt "Goto" besser "Go Away" angebracht...

von Zeno (Gast)


Lesenswert?

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

von Rolf M. (rmagnus)


Lesenswert?

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.

: Bearbeitet durch User
von Mikro 7. (mikro77)


Lesenswert?

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.
1
sighandler(int)
2
{
3
    // ...
4
}

von Bernd K. (prof7bit)


Lesenswert?

Rolf M. schrieb:
> Es gibt ja auch noch den eigentlich viel cooleren umgekehrten Konstrukt
> names COMEFROM.

Auch unter dem Namen catch oder except bekannt.

von Rolf M. (rmagnus)


Lesenswert?

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.

von M. K. (sylaina)


Lesenswert?

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.

von Einer K. (Gast)


Lesenswert?

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.

von Rolf M. (rmagnus)


Lesenswert?

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.

von M. K. (sylaina)


Lesenswert?

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? :D

M. 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
int add (int a, int b){
2
  return a + b;
3
}

Was muss ich hier tun, dass b nicht mehr benutzt wird? Genau, ich muss 
die Funktion ändern:
1
int add (int a, int b){
2
  return a;
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)

von Mikro 7. (mikro77)


Lesenswert?

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".

von Walter S. (avatar)


Lesenswert?

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?

von Mikro 7. (mikro77)


Lesenswert?

1
int callback(int red,int,int)

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Walter S. schrieb:
> Was machst Du in dem Fall mit der Warnung des Compilers?
1
__attribute__((unused))

von Konrad S. (maybee)


Lesenswert?

Jörg W. schrieb:
> Walter S. schrieb:
>> Was machst Du in dem Fall mit der Warnung des Compilers?
>
>
1
__attribute__((unused))

Im Prinzip ja ... aber ein
1
(void)x;
versteht sogar der MSVC-Compiler.

von Paul B. (paul_baumann)


Lesenswert?

Jeden Tag werde ich froher darüber, nicht C oder C-Ähnliches benutzen zu 
müssen.

SCNR
-Paul-

von Konrad S. (maybee)


Lesenswert?

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. ;-)

von Dussel (Gast)


Lesenswert?

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.

von Michael S. (rbs_phoenix)


Lesenswert?

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" ;)

von Walter S. (avatar)


Lesenswert?

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

von M. K. (sylaina)


Lesenswert?

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.

: Bearbeitet durch User
von Yalu X. (yalu) (Moderator)


Lesenswert?

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?

von Falk B. (falk)


Lesenswert?

@ 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 
;-)

von M. K. (sylaina)


Lesenswert?

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.

von Einer K. (Gast)


Lesenswert?

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

von Yalu X. (yalu) (Moderator)


Lesenswert?

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.

von Bernd K. (prof7bit)


Lesenswert?

M. K. schrieb:
> Aber warum sollte dann ein Parameter einer Funktion einer API
> unbenutzt sein?

Es geht um Callback-Funktionen.

von W.S. (Gast)


Lesenswert?

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.

von visitor (Gast)


Lesenswert?

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!

von M. K. (sylaina)


Lesenswert?

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).

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.)

: Bearbeitet durch Moderator
von nicht"Gast" (Gast)


Lesenswert?

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.

von nichtCler (Gast)


Lesenswert?

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*

von nicht"Gast" (Gast)


Lesenswert?

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 :).

von Heinz L. (ducttape)


Lesenswert?

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.

von nicht"Gast" (Gast)


Lesenswert?

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 :)

von M. K. (sylaina)


Lesenswert?

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? ;)

von Heinz L. (ducttape)


Lesenswert?

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.

von M. K. (sylaina)


Lesenswert?

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?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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:
1
% find ~/src/linux-3.13 -name '*.c' | xargs fgrep -w goto | wc -l
2
114601

von Karl (Gast)


Lesenswert?

Die ganze Diskussion ist sinnlos. wie man an den Ursprüngen von Fotran 
sehen kann sind alle Schleifen und Zweige nur verkappte 
GOTO-Anweisungen.

https://de.wikibooks.org/wiki/Fortran:_FORTRAN_77:_Verzweigungen_und_Schleifen#Weitere_Schleifen

Ob man also GOTO oder was anderes verwendet ist reine syntaktische 
Kosmetik!

von nicht"Gast" (Gast)


Lesenswert?

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.

von Mark B. (markbrandis)


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.)

von Mark B. (markbrandis)


Lesenswert?

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. ;-)

: Bearbeitet durch User
von Yalu X. (yalu) (Moderator)


Lesenswert?

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.

von nicht"Gast" (Gast)


Lesenswert?

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 :)

von Clemens M. (panko)


Lesenswert?

1
void usb_process_request(void)
2
{
3
  U8 bRequest;
4
5
  Usb_reset_endpoint_fifo_access(EP_CONTROL);
6
  bmRequestType = Usb_read_endpoint_data(EP_CONTROL, 8);
7
  bRequest      = Usb_read_endpoint_data(EP_CONTROL, 8);
8
9
  switch (bRequest)
10
  {
11
  case GET_DESCRIPTOR:
12
    if (bmRequestType == 0x80) usb_get_descriptor();
13
    else goto unsupported_request;
14
    break;
15
16
  case GET_CONFIGURATION:
17
    if (bmRequestType == 0x80) usb_get_configuration();
18
    else goto unsupported_request;
19
    break;
20
21
  case SET_ADDRESS:
22
    if (bmRequestType == 0x00) usb_set_address();
23
    else goto unsupported_request;
24
    break;
25
26
  case SET_CONFIGURATION:
27
    if (bmRequestType == 0x00) usb_set_configuration();
28
    else goto unsupported_request;
29
    break;
30
31
  case CLEAR_FEATURE:
32
    if (bmRequestType <= 0x02) usb_clear_feature();
33
    else goto unsupported_request;
34
    break;
35
36
  case SET_FEATURE:
37
    if (bmRequestType <= 0x02) usb_set_feature();
38
    else goto unsupported_request;
39
    break;
40
41
  case GET_STATUS:
42
    if (0x7F < bmRequestType && bmRequestType <= 0x82) usb_get_status();
43
    else goto unsupported_request;
44
    break;
45
46
  case GET_INTERFACE:
47
    if (bmRequestType == 0x81)
48
    {
49
      if(!usb_get_interface())
50
      {
51
        Usb_enable_stall_handshake(EP_CONTROL);
52
        Usb_ack_setup_received_free();
53
      }
54
    }
55
    else goto unsupported_request;
56
    break;
57
58
  case SET_INTERFACE:
59
    if (bmRequestType == 0x01) usb_set_interface();
60
    else
61
      goto unsupported_request;
62
    break;
63
64
  case SET_DESCRIPTOR:
65
  case SYNCH_FRAME:
66
  default:  //!< unsupported request => call to user read request
67
  unsupported_request:
68
    if (!usb_user_read_request(bmRequestType, bRequest))
69
    {
70
      Usb_enable_stall_handshake(EP_CONTROL) ;
71
      Usb_ack_setup_received_free();
72
    }
73
    break;
74
  }
75
}

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

: Bearbeitet durch User
von Rudi D. (rudi_d)


Lesenswert?

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!

von Heinz L. (ducttape)


Lesenswert?

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.

von Mark B. (markbrandis)


Lesenswert?

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.

: Bearbeitet durch User
von Zeno (Gast)


Lesenswert?

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.

von Zeno (Gast)


Lesenswert?

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

von Paul B. (paul_baumann)


Lesenswert?

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

von Marc (Gast)


Lesenswert?

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

von W.S. (Gast)


Lesenswert?

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.

von Zeno (Gast)


Lesenswert?

W.S. schrieb:
> auf einem µC überhaupt ...


Und wenn man aus dem µC einen µP macht dann gehört eigentlich noch was 
ganz anderes auf den Prüfstand !

Zeno

von Mark B. (markbrandis)


Lesenswert?

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.

von Mark B. (markbrandis)


Lesenswert?

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.

von Zeno (Gast)


Lesenswert?

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

von MCUA (Gast)


Lesenswert?

>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.

von Mark B. (markbrandis)


Lesenswert?

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?

von Programmierer (Gast)


Lesenswert?

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:

1
void usb_process_request(void)
2
{
3
    U8 bRequest;
4
5
    Usb_reset_endpoint_fifo_access(EP_CONTROL);
6
    bmRequestType = Usb_read_endpoint_data(EP_CONTROL, 8);
7
    bRequest      = Usb_read_endpoint_data(EP_CONTROL, 8);
8
9
    if (bRequest == GET_DESCRIPTOR && bmRequestType == 0x80)
10
        usb_get_descriptor();
11
12
    else if (bRequest == GET_CONFIGURATION && bmRequestType == 0x80)
13
        usb_get_configuration();
14
15
    else if (bRequest == SET_ADDRESS && bmRequestType == 0x00)
16
        usb_set_address();
17
18
    else if (bRequest == SET_CONFIGURATION && bmRequestType == 0x00) 
19
        usb_set_configuration();
20
21
    else if (bRequest == CLEAR_FEATURE && bmRequestType <= 0x02) 
22
        usb_clear_feature();
23
24
    else if (bRequest == SET_FEATURE && bmRequestType <= 0x02) 
25
        usb_set_feature();
26
27
    else if (bRequest == GET_STATUS && 0x7F < bmRequestType && bmRequestType <= 0x82) 
28
        usb_get_status();
29
30
    else if (bRequest == GET_INTERFACE && bmRequestType == 0x81)
31
    {
32
        if(!usb_get_interface())
33
        {
34
            Usb_enable_stall_handshake(EP_CONTROL);
35
            Usb_ack_setup_received_free();
36
        }
37
    }
38
39
    else if (bRequest == SET_INTERFACE && bmRequestType == 0x01) 
40
        usb_set_interface();
41
42
    else // unsupported request => call to user read request
43
    {
44
        if (!usb_user_read_request(bmRequestType, bRequest))
45
        {
46
            Usb_enable_stall_handshake(EP_CONTROL) ;
47
            Usb_ack_setup_received_free();
48
        }
49
    }
50
}

von Marc (Gast)


Lesenswert?

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;

von Zeno (Gast)


Lesenswert?

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.

von Zeno (Gast)


Lesenswert?

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!

von nicht"Gast" (Gast)


Lesenswert?

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.

von Zeno (Gast)


Lesenswert?

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.

von Clemens M. (panko)


Lesenswert?

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.

von Clemens M. (panko)


Lesenswert?

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.

von M. K. (sylaina)


Lesenswert?

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.

von nicht"Gast" (Gast)


Lesenswert?

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.

von Michael S. (rbs_phoenix)


Lesenswert?

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
  goto Schleifenbeginn;
5
}
6
goto Schleifenende;
7
8
Schleifenbeginn:
9
// Schleifeninhalt
10
goto Schleifenbedingung;
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.

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Zeno (Gast)


Lesenswert?

nicht"Gast" schrieb:
> Wozu ist der RequestType gut?

Keine Ahnung, da müßte man den kompletten Code sehen. Das gepostete ist 
ja nur ein Auszug.

von Zeno (Gast)


Lesenswert?

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.

von Zeno (Gast)


Lesenswert?

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.

von Zeno (Gast)


Lesenswert?

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!

von nicht"Gast" (Gast)


Lesenswert?

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.

von M. K. (sylaina)


Lesenswert?

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...

von Zeno (Gast)


Lesenswert?

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.

von Zeno (Gast)


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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:
1
    case GET_CONFIGURATION:
2
        if (bmRequestType == (DIR_IN | RQTYPE_STANDARD | RQRCPT_DEVICE))
3
        {
4
            UEINTX &= ~_BV(RXSTPI);
5
            get_configuration();
6
            break;
7
        }
8
        return false;
9
10
    case GET_DESCRIPTOR:
11
        if (bmRequestType == (DIR_IN | RQTYPE_STANDARD | RQRCPT_DEVICE))
12
        {
13
            /* descriptor type */
14
            switch (wValue >> 8)
15
            {
16
            case DEVICE_DESC:
17
                if (wIndex == 0)
18
                {
19
                    UEINTX &= ~_BV(RXSTPI);
20
                    get_flash_descriptor((const char *)&device_desc,
21
                                         sizeof(device_desc), wLength);
22
                    break;
23
                }
24
                return false;
25
26
            case CONFIGURATION_DESC:
27
                if (wIndex == 0)
28
                {
29
                    UEINTX &= ~_BV(RXSTPI);
30
                    get_flash_descriptor((const char *)&configuration_desc,
31
                                         sizeof(configuration_desc), wLength);
32
                    break;
33
                }
34
                return false;
35
36
            case STRING_DESC:
37
                /* descriptor index */
38
                switch (wValue & 0xFF)
39
                {
40
                    uint8_t len;
41
42
                case 0:
43
                    UEINTX &= ~_BV(RXSTPI);
44
45
                    /* .bLength of actual descriptor */
46
                    len = pgm_read_byte(&string_descriptor_langs);
47
                    get_flash_descriptor((const char *)&string_descriptor_langs,
48
                                         len, wLength);
49
                    break;

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.

: Bearbeitet durch Moderator
von Ralf G. (ralg)


Lesenswert?

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!

von Mark B. (markbrandis)


Lesenswert?

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.

von nicht"Gast" (Gast)


Lesenswert?

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.

von Mark B. (markbrandis)


Lesenswert?

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.

von Clemens M. (panko)


Lesenswert?

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.

von Michael S. (rbs_phoenix)


Lesenswert?

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.

von Mark B. (markbrandis)


Lesenswert?

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.

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

@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 ;-)
1
void usb_process_request(void)
2
{
3
  U8 bRequest;
4
5
  Usb_reset_endpoint_fifo_access(EP_CONTROL);
6
  bmRequestType = Usb_read_endpoint_data(EP_CONTROL, 8);
7
  bRequest      = Usb_read_endpoint_data(EP_CONTROL, 8);
8
  U8 unsupported = 1;
9
10
  switch (bRequest)
11
  {
12
  case GET_DESCRIPTOR:
13
    if (bmRequestType == 0x80) {
14
      usb_get_descriptor();
15
      unsupported = 0;
16
    }
17
    break;
18
19
  case GET_CONFIGURATION:
20
    if (bmRequestType == 0x80) {
21
      usb_get_configuration();
22
      unsupported = 0;
23
    }
24
    break;
25
26
  case SET_ADDRESS:
27
    if (bmRequestType == 0x00) {
28
      usb_set_address();
29
      unsupported = 0;
30
    }
31
    break;
32
33
  case SET_CONFIGURATION:
34
    if (bmRequestType == 0x00) {
35
      usb_set_configuration();
36
      unsupported = 0;
37
    }
38
    break;
39
40
  case CLEAR_FEATURE:
41
    if (bmRequestType <= 0x02) {
42
      usb_clear_feature();
43
      unsupported = 0;
44
    }
45
    break;
46
47
  case SET_FEATURE:
48
    if (bmRequestType <= 0x02) {
49
      usb_set_feature();
50
      unsupported = 0;
51
    }
52
    break;
53
54
  case GET_STATUS:
55
    if (0x7F < bmRequestType && bmRequestType <= 0x82) {
56
      usb_get_status();
57
      unsupported = 0;
58
    }
59
    break;
60
61
  case GET_INTERFACE:
62
    if (bmRequestType == 0x81)
63
    {
64
      if(!usb_get_interface())
65
      {
66
        Usb_enable_stall_handshake(EP_CONTROL);
67
        Usb_ack_setup_received_free();
68
      }
69
      unsupported = 0; 
70
    }
71
    break;
72
73
  case SET_INTERFACE:
74
    if (bmRequestType == 0x01) {
75
      usb_set_interface();
76
      unsupported = 0;
77
    }
78
    break;
79
80
  case SET_DESCRIPTOR:
81
  case SYNCH_FRAME:
82
  default:
83
    break;
84
  }
85
86
  // unsupported request => call to user read request
87
  if (unsupported) {
88
    if (!usb_user_read_request(bmRequestType, bRequest))
89
    {
90
      Usb_enable_stall_handshake(EP_CONTROL) ;
91
      Usb_ack_setup_received_free();
92
    }
93
  }
94
}

von Ralf G. (ralg)


Lesenswert?

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.

von Mark B. (markbrandis)


Lesenswert?

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?

von Ralf G. (ralg)


Lesenswert?

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 :-)

von Michael S. (rbs_phoenix)


Lesenswert?

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.

von Ralf G. (ralg)


Lesenswert?

Ralf G. schrieb:
> So steht wenigstens noch was drin :-)

Falk B. schrieb:
1
  case SET_DESCRIPTOR:
2
  case SYNCH_FRAME:
3
  default:
4
    break;
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:

: Bearbeitet durch User
von nicht"Gast" (Gast)


Lesenswert?

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 ^^)

von Clemens M. (panko)


Lesenswert?

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.

von nicht"Gast" (Gast)


Lesenswert?

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:
1
struct setupPacket readPacket // blablabla initialisieren, einlesens u.s.w
2
3
case SET_INTERFACE:    
4
    usb_set_interface(&readPacket);    
5
    break;

dann ist das alles schon vom Stack gelesen und braucht keine 
Resteleserampe (wenn ich das richtig verstanden habe).

http://www.beyondlogic.org/usbnutshell/usb6.shtml

von M. K. (sylaina)


Lesenswert?

Michael S. schrieb:
> Wieso das?

Weil deren Programm sonst weiterhin suggerieren wird, dass die 
Temperatur noch eine Rolle spielt.

von Zeno (Gast)


Lesenswert?

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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Zeno (Gast)


Lesenswert?

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

von Zeno (Gast)


Lesenswert?

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

von M. K. (sylaina)


Lesenswert?

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.

von Zeno (Gast)


Lesenswert?

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.

von Karl Käfer (Gast)


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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 …

von Clemens M. (panko)


Lesenswert?

Um mal Zenos Punkt zu stützen kann man auch wieder relativieren. Wie 
immer im Leben.
1
uint32_t timeout = tick_ms + 100;
2
while( tick_ms < timeout) {
3
(...)
4
}
5
6
gegen
7
#define TIMEOUT_MS 100
8
9
uint32_t timeout = 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.

von chris_ (Gast)


Lesenswert?

Da der Thread immer länger wird, kennt Ihr den schon:
Beitrag ""goto"-Befehl in C"

von Yalu X. (yalu) (Moderator)


Lesenswert?

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

von nichtCler (Gast)


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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).

von W.S. (Gast)


Lesenswert?

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.

von W.S. (Gast)


Lesenswert?

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.

von W.S. (Gast)


Lesenswert?

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.

von Zeno (Gast)


Lesenswert?

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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Daniel A. (daniel-a)


Lesenswert?

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.

von M. K. (sylaina)


Lesenswert?

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.

von chris_ (Gast)


Lesenswert?

Ich hätte da noch einen:
Beitrag "goto in c warum"

von Mark B. (markbrandis)


Lesenswert?

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! ;-)

: Bearbeitet durch User
von Michael S. (rbs_phoenix)


Lesenswert?

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 ;)

von Mitlesender (Gast)


Lesenswert?

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.

von Paul B. (paul_baumann)


Lesenswert?

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

von Mark B. (markbrandis)


Lesenswert?

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.

von Daniel A. (daniel-a)


Lesenswert?

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

von Eric B. (beric)


Lesenswert?

Paul B. schrieb:
> Man kann damit aus einer Routine abzwitschern und damit Chaos
> hinterlassen.

...dann sei no nett und benutz' die Bürste :-P

von Paul B. (paul_baumann)


Lesenswert?

Ich mach' ein Selfie-Foto
Arm in Arm mit meinem GOTO
und schreib dazu noch einen Text
das nehm' ich mir fest FOR
demNEXT!

MfG Paul

von Stefan (Gast)


Lesenswert?


von berndl (Gast)


Lesenswert?

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...

von W.S. (Gast)


Lesenswert?

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.

von Mark B. (markbrandis)


Lesenswert?

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."

: Bearbeitet durch User
von Mark B. (markbrandis)


Lesenswert?

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.

von geh (Gast)


Lesenswert?

Goto ist nur was für richtige Männer.

von Paul B. (paul_baumann)


Lesenswert?

geh schrieb:
> Goto ist nur was für richtige Männer.

Es gibt durchaus auch Frauen,
die sich an GOTO trauen!

MfG Paul

von nichtCler (Gast)


Lesenswert?

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?

von dummschwaetzer (Gast)


Lesenswert?

da nehm ich
#pragma diag_suppress= ###
//der code der die Warnung wirft
#pragma diag_warning= ###

von Michael S. (rbs_phoenix)


Lesenswert?

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 ;)

von MCUA (Gast)


Lesenswert?

> Und wenn ich die Schritte der Sequenz in einzelne Funktionen aufteile..
einzelne Funktionen kosten in der Regel jedoch viel mehr CPU-Rechenzeit

von Zeno (Gast)


Lesenswert?

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

von M. K. (sylaina)


Lesenswert?

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.

von Yalu X. (yalu) (Moderator)


Lesenswert?

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.

von Paul B. (paul_baumann)


Lesenswert?

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

von Yalu X. (yalu) (Moderator)


Lesenswert?

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

von Herbert P. (Gast)


Lesenswert?

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

von Cube_S (Gast)


Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

@  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ß!

von Cube_S (Gast)


Lesenswert?

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.

von Yalu X. (yalu) (Moderator)


Lesenswert?

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.

von Chris F. (chfreund) Benutzerseite


Lesenswert?

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.

von Mark B. (markbrandis)


Lesenswert?

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.

von Rasputin (Gast)


Lesenswert?

Zu dem Thema hab ich auch ein lustiges Fundstück:
1
#define MAXINT 200000
2
3
int main(void) 
4
{
5
    unsigned int t=1000, k=0, l=5, pn=2; 
6
    unsigned int primes[t];
7
    primes[0]=2;
8
    primes[1]=3;
9
10
    while (pn < t || primes[pn] < MAXINT)
11
    {
12
        for ( k = 0; k <= pn; k++)
13
        {
14
            if (l % primes[k] == 0)
15
      {
16
                goto otog;
17
      }
18
            else 
19
            {
20
                if (k == pn)
21
                    primes[pn++]=l;
22
            } 
23
        }
24
otog:
25
        l += 2;
26
    }
27
    return 0;
28
}

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. ;)

von Falk B. (falk)


Lesenswert?

Auch bei Atmel arbeiten billige Praktikanten und Frickler . . .

von Paul B. (paul_baumann)


Lesenswert?

>> 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

von Cube_S (Gast)


Lesenswert?

> Abgesehen davon, dass dieser Code fehlerhaft ist

Warum? Der Return-Wert ist 0. Das stimmt doch.

von W.S. (Gast)


Lesenswert?

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.

von Bernd K. (prof7bit)


Lesenswert?

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++.

von Thorsten .. (tms320)


Lesenswert?

> 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.

von Falk B. (falk)


Lesenswert?

@ 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 ;-)

von Timm R. (Firma: privatfrickler.de) (treinisch)


Lesenswert?

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

von Zeno (Gast)


Lesenswert?

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 Sparte


Herbert 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:
1
 again:
2
  if (port++ >= TCP_LOCAL_PORT_RANGE_END) {
3
    port = TCP_LOCAL_PORT_RANGE_START;
4
  }
5
  /* Check all PCB lists. */
6
  for (i = 0; i < NUM_TCP_PCB_LISTS; i++) {
7
    for(pcb = *tcp_pcb_lists[i]; pcb != NULL; pcb = pcb->next) {
8
      if (pcb->local_port == port) {
9
        goto again;
10
      }
11
    }
12
  }
13
  return port;
14
}

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

von Zeno (Gast)


Lesenswert?

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

von M. K. (sylaina)


Lesenswert?

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.

von nichtCler (Gast)


Lesenswert?

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.

von Mark B. (markbrandis)


Lesenswert?

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.

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

@ 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.html

https://en.wikipedia.org/wiki/Therac-25

1
  do {
2
    if (port++ >= TCP_LOCAL_PORT_RANGE_END) {
3
      port = TCP_LOCAL_PORT_RANGE_START;
4
    }
5
    /* Check all PCB lists. */
6
    for (i = 0; i < NUM_TCP_PCB_LISTS; i++) {
7
      for(pcb = *tcp_pcb_lists[i]; pcb != NULL; pcb = pcb->next) {
8
        if (pcb->local_port == port) break;
9
      }
10
      if (pcb->local_port == port) break;
11
    }
12
  } while (pcb->local_port == port);
13
14
  return port;
15
}

Das war jetzt echt schwer ohne goto . . .

von M. K. (sylaina)


Lesenswert?

Falk B. schrieb:
> Das war jetzt echt schwer ohne goto . . .

Ehrlich gesagt finde ich die Variante mit goto in dem Fall etwas 
übersichtlicher (!= besser).

von Timm R. (Firma: privatfrickler.de) (treinisch)


Lesenswert?

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
  case GET_DESCRIPTOR:
2
    if (bmRequestType == 0x80) usb_get_descriptor();
3
    else goto unsupported_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

: Bearbeitet durch User
von Mark B. (markbrandis)


Lesenswert?

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.

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

@ 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.

von MCUA (Gast)


Lesenswert?

> 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)

von Zeno (Gast)


Lesenswert?

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

von Daniel A. (daniel-a)


Lesenswert?

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 ;)

von M. K. (sylaina)


Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

@ 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!

von Falk B. (falk)


Lesenswert?

@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 . . .

von Mark B. (markbrandis)


Lesenswert?

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. ;-)

: Bearbeitet durch User
von Daniel A. (daniel-a)


Lesenswert?

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.

von nichtCler (Gast)


Lesenswert?

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?

von Zeno (Gast)


Lesenswert?

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.

von Zeno (Gast)


Lesenswert?

Falk B. schrieb:
> Ein hohes Niveau sieht nur von unten wie Arroganz aus ;-)

Wußte nicht das Arroganz noch steigerungsfähig ist.

von Zeno (Gast)


Lesenswert?

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.

von Zeno (Gast)


Lesenswert?

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

von Zeno (Gast)


Lesenswert?

@nichtCler
Bevor Du wieder meckerst, ja ich habe einen Fehler gemacht und ein 
Leerzeichen vergessen.
Zeno schrieb:
> eingewisser

Korrektur: ein gewisser

von M. K. (sylaina)


Lesenswert?

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 ;)

von Daniel A. (daniel-a)


Lesenswert?

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?

von nichtCler (Gast)


Lesenswert?

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.

von Programmierer (Gast)


Lesenswert?

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
  case A:
4
    if (something)
5
      action();
6
    else
7
      goto label;
8
    break;
9
10
  ...
11
}

1
switch (x)
2
{
3
  case A:
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.

von Programmierer (Gast)


Lesenswert?

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.

von M. K. (sylaina)


Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

@ 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!

von rhf (Gast)


Lesenswert?

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

von M. K. (sylaina)


Lesenswert?

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.

von sepp (Gast)


Lesenswert?

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.

von MCUA (Gast)


Lesenswert?

>Der ganze Programmablauf beruht komplett auf verschachtelte Sprünge.
Es gibt keine verschachtelte Sprünge.

von Mark B. (markbrandis)


Lesenswert?

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.

: Bearbeitet durch User
von blablablubb (Gast)


Lesenswert?

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.

von Mark B. (markbrandis)


Lesenswert?

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?

: Bearbeitet durch User
von MCUA (Gast)


Lesenswert?

>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!

von Mark B. (markbrandis)


Lesenswert?

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.

: Bearbeitet durch User
von Mikro 7. (mikro77)


Lesenswert?

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.

von Mark B. (markbrandis)


Lesenswert?

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? ;-)

von Walter S. (avatar)


Lesenswert?

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

: Bearbeitet durch User
von Walter S. (avatar)


Lesenswert?

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;
  }

: Bearbeitet durch User
von MCUA (Gast)


Lesenswert?

>> 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.

von Falk B. (falk)


Lesenswert?

@ 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.

1
  int i = TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START;
2
  found = 1;
3
4
  for (; found && i>0; i--) {    
5
    if (port++ >= TCP_LOCAL_PORT_RANGE_END) {
6
      port = TCP_LOCAL_PORT_RANGE_START;
7
    }
8
    /* Check all PCB lists for port occurance */    
9
    for (i = 0, found = 0; !found && i < NUM_TCP_PCB_LISTS; i++) {
10
      for(pcb = *tcp_pcb_lists[i]; !found && pcb != NULL; pcb = pcb->next) {
11
        if (pcb->local_port == port) found = 1;
12
      }
13
    }
14
  }
15
16
  if (i==0) {
17
    // error, all ports are in lists
18
    return ERROR;
19
  } else {
20
    return port;    // port is not in lists
21
  }

Und jetzt werden die Goto-ianer wieder über die Hilfsvariable found 
lästern ;-)

: Bearbeitet durch User
von Zeno (Gast)


Lesenswert?

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

von Daniel A. (daniel-a)


Lesenswert?

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.

von Zeno (Gast)


Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

War noch ein kleiner Fehler drin 8-0
So ist es richtig und LESBAR!!!
1
  int i = TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START;
2
  found = 1;
3
4
  for (; found && i>0; i--) {    
5
    if (port++ >= TCP_LOCAL_PORT_RANGE_END) {
6
      port = TCP_LOCAL_PORT_RANGE_START;
7
    }
8
    /* Check all PCB lists for port occurance */    
9
    for (i = 0, found = 0; !found && i < NUM_TCP_PCB_LISTS; i++) {
10
      for(pcb = *tcp_pcb_lists[i]; !found && pcb != NULL; pcb = pcb->next) {
11
        if (pcb->local_port == port) found = 1;
12
      }
13
    }
14
  }
15
16
  if (found) {    
17
    return 0;       // error, all ports are in lists
18
  } else {
19
    return port;    // port is not in lists
20
  }

von Zeno (Gast)


Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

@ 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.

von blablablubb (Gast)


Lesenswert?

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.

von Mark B. (markbrandis)


Lesenswert?

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.

von blablablubb (Gast)


Lesenswert?

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.

von Mark B. (markbrandis)


Lesenswert?

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.

: Bearbeitet durch User
von blablablubb (Gast)


Lesenswert?

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.

von Yalu X. (yalu) (Moderator)


Lesenswert?

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:

1
static bool port_is_in_use(u16_t port) {
2
  struct tcp_pcb *pcb;
3
  int i;
4
5
  for (i = 0; i < NUM_TCP_PCB_LISTS; i++) {
6
    for(pcb = *tcp_pcb_lists[i]; pcb != NULL; pcb = pcb->next) {
7
      if (pcb->local_port == port)
8
        return true;
9
    }
10
  }
11
  return false;
12
}
13
14
static u16_t tcp_new_port(void) {
15
  static u16_t port = TCP_LOCAL_PORT_RANGE_START;
16
17
  do {
18
    if (port++ >= TCP_LOCAL_PORT_RANGE_END)
19
      port = TCP_LOCAL_PORT_RANGE_START;
20
  } while(port_is_in_use(port));
21
22
  return port;
23
}

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
5
 * new TCP local port.
6
 */

;-)

von Zeno (Gast)


Lesenswert?

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.

von Daniel A. (daniel-a)


Lesenswert?

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.

von Zeno (Gast)


Lesenswert?

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

von Zeno (Gast)


Lesenswert?

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.

von Daniel A. (daniel-a)


Lesenswert?

Heute scheint irgendwie nicht mein Tag zu sein...

von Walter S. (avatar)


Lesenswert?

Falk B. schrieb:
> War noch ein kleiner Fehler drin 8-0
> So ist es richtig

fast ;-)
i wird doppelt verwendet

von blablablubb (Gast)


Lesenswert?

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.

von Mark B. (markbrandis)


Lesenswert?

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.

von Mark B. (markbrandis)


Lesenswert?

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, ...

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

@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!

;-)

von blablablubb (Gast)


Lesenswert?

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.

von Mark B. (markbrandis)


Lesenswert?

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.

von blablablubb (Gast)


Lesenswert?

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.

von blablablubb (Gast)


Lesenswert?

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.

von Mark B. (markbrandis)


Lesenswert?

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.

: Bearbeitet durch User
von Mark B. (markbrandis)


Lesenswert?

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

;-)

von blablablubb (Gast)


Lesenswert?

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.

von blablablubb (Gast)


Lesenswert?

Mark B. schrieb:
> Mit "viele" meinst Du sicher:
>...

Ja, unter anderem. Endlich hast du mal ein paar der immer wieder 
vorgetragenen Beispiele gefunden. Bravo.

von Mark B. (markbrandis)


Lesenswert?

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".

von Zeno (Gast)


Lesenswert?

Mark B. schrieb:
> Dann ist eine Diskussion freilich sinnlos.

Mal an die eigene Nase fassen.

von blablablubb (Gast)


Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

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 . . .
1
static u16_t tcp_new_port(void) {
2
  static u16_t port = TCP_LOCAL_PORT_RANGE_START;
3
  u16_t i;
4
5
  for (i=0xFFFF; i>0; i--) {
6
    if (port++ >= TCP_LOCAL_PORT_RANGE_END) {
7
      port = TCP_LOCAL_PORT_RANGE_START;
8
    }
9
    if (!port_is_in_use(port)) break;
10
  }
11
12
  if (i==0) {
13
    return 0;       // error, no more free ports
14
  } else {
15
    return port;
16
  }
17
}

von Zeno (Gast)


Lesenswert?

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

von blablablubb (Gast)


Lesenswert?

Falk B. schrieb:
> u16_t i;
>
>   for (...; i>0; ...) {

Ach bitte...

von Daniel A. (daniel-a)


Lesenswert?

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:
1
u16_t i;
2
for( i=0; --i; ) {
3
...

von blablablubb (Gast)


Lesenswert?

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.

von Zeno (Gast)


Lesenswert?

Falk B. schrieb:
> for (i=0xFFFF;

ÄÄÄÄH waren magic Number nich schlechter Programmierstil - hat mir in 
diesem Thread gesagt.

Zeno

von Timm R. (Firma: privatfrickler.de) (treinisch)


Lesenswert?

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

von Herbert P. (Gast)


Lesenswert?

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

von Mark B. (markbrandis)


Lesenswert?

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.

von Yalu X. (yalu) (Moderator)


Lesenswert?

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.

von Mark B. (markbrandis)


Lesenswert?

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. :-(

von Tommi (Gast)


Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

Schaff ich das noch heute noch?
1
static u16_t tcp_new_port(void) {
2
  static u16_t port = TCP_LOCAL_PORT_RANGE_START;
3
  u16_t i = TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START;
4
5
  for (; i>0; i--) {
6
    if (port++ >= TCP_LOCAL_PORT_RANGE_END) {
7
      port = TCP_LOCAL_PORT_RANGE_START;
8
    }
9
    if (!port_is_in_use(port)) break;
10
  }
11
12
  if (i==0) {
13
    return 0;       // error, no more free ports
14
  } else {
15
    return port;
16
  }
17
}

von blablablubb (Gast)


Lesenswert?

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.

von Timm R. (Firma: privatfrickler.de) (treinisch)


Lesenswert?

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

von Zeno (Gast)


Lesenswert?

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

von blablablubb (Gast)


Lesenswert?

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??

von blablablubb (Gast)


Lesenswert?

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 :)

von blablablubb (Gast)


Lesenswert?

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).

von Tommi (Gast)


Lesenswert?

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.

von Zeno (Gast)


Lesenswert?

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

von blablablubb (Gast)


Lesenswert?

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.

von blablablubb (Gast)


Lesenswert?

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.

von blablablubb (Gast)


Lesenswert?

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.

von Zeno (Gast)


Lesenswert?

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

von Zeno (Gast)


Lesenswert?

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

von Daniel A. (daniel-a)


Lesenswert?

Ich denke es geht um soein Konstrukt?
1
bool do_something( const char* a, const char* b ){
2
3
  bool success = false;
4
5
  FILE* f1 = fopen(a,"r");
6
  if(!f1)
7
    goto cleanup1;
8
9
  FILE* f2 = fopen(b,"w");
10
  if(!f2)
11
    goto cleanup2;
12
13
  if( do_something_with_files(f1,f2) ){
14
    success = true;
15
  }else{
16
    goto cleanup3;
17
  }
18
19
 cleanup3:
20
  fclose(f2);
21
 cleanup2:
22
  fclose(f1);
23
 cleanup1:
24
  return success;
25
}

von Zeno (Gast)


Lesenswert?

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

von Zeno (Gast)


Lesenswert?

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

von blablablubb (Gast)


Lesenswert?

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.

von Daniel A. (daniel-a)


Lesenswert?

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 ;)

: Bearbeitet durch User
von blablablubb (Gast)


Lesenswert?

Daniel A. schrieb:
> Na dann bin ich mal froh, das mein Konstrukt im (nicht) Fehlerfall alle
> Aufräumarbeiten macht ;)

Du hast es nicht verstanden.

von Daniel A. (daniel-a)


Lesenswert?

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...

von Zeno (Gast)


Lesenswert?

Daniel A. schrieb:
> Ach so, es ging darum dass die Klammern bei try - finally verhindern,

Äh wo sind bei meinem try/finally Klammern ?????

Zeno

von Zeno (Gast)


Lesenswert?

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)
9
end;


Zeno

von blablablubb (Gast)


Lesenswert?

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.

von Zeno (Gast)


Lesenswert?

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.

von Mark B. (markbrandis)


Lesenswert?

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.

von Mark B. (markbrandis)


Lesenswert?

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.

: Bearbeitet durch User
von M. K. (sylaina)


Lesenswert?

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?

von blablablubb (Gast)


Lesenswert?

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.

von Mitlesender (Gast)


Lesenswert?

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

von Programmierer (Gast)


Lesenswert?

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".

von blablablubb (Gast)


Lesenswert?

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)

von S. R. (svenska)


Lesenswert?

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.

von M. K. (sylaina)


Lesenswert?

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.

von Mark B. (markbrandis)


Lesenswert?

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".

von Mark B. (markbrandis)


Lesenswert?

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

: Bearbeitet durch User
von blablablubb (Gast)


Lesenswert?

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?

von Mark B. (markbrandis)


Lesenswert?

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.

: Bearbeitet durch User
von blablablubb (Gast)


Lesenswert?

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?

von W.S. (Gast)


Lesenswert?

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.

von Daniel A. (daniel-a)


Lesenswert?

Die Diskussion war doch von Anfang an zum scheitern verurteilt, oder hat 
irgendjemand seine goto-Meinung geändert?

https://youtu.be/YbX0wwp-nlI

: Bearbeitet durch User
von Yalu X. (yalu) (Moderator)


Lesenswert?

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.

von Zeno (Gast)


Lesenswert?

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

von Zeno (Gast)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

von Zeno (Gast)


Lesenswert?

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

von Mark B. (markbrandis)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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... ;-)

von Falk B. (falk)


Lesenswert?

Self fullfilling prophecy . . .  ;-)

von Lalala (Gast)


Lesenswert?

Selbst Kernigham hat es schon etwas differenzierter ausgedrueckt als in 
die Buchfassung hier herausgelesen wIrd:
https://www.lysator.liu.se/c/bwk-tutor.html#goto

von H.Joachim S. (crazyhorse)


Lesenswert?

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.

von Timm R. (Firma: privatfrickler.de) (treinisch)


Lesenswert?

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

von Vintage (Gast)


Lesenswert?

Vintage ist doch in. Mit goto kommt das Basic Feeling zurück. ;-)))

von Timm R. (Firma: privatfrickler.de) (treinisch)


Lesenswert?

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

: Bearbeitet durch User
von Mark B. (markbrandis)


Lesenswert?

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

von Zeno (Gast)


Lesenswert?

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.

von chris_ (Gast)


Lesenswert?

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.

von M. K. (sylaina)


Lesenswert?

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 ;)

von chris_ (Gast)


Lesenswert?

>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?

von M. K. (sylaina)


Lesenswert?

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.

: Bearbeitet durch User
von Mark B. (markbrandis)


Lesenswert?

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?

: Bearbeitet durch User
von MCUA (Gast)


Lesenswert?

>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.

von Michael B. (laberkopp)


Lesenswert?

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.

von Mark B. (markbrandis)


Lesenswert?

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?

von Yalu X. (yalu) (Moderator)


Lesenswert?

Michael B. schrieb:
> Bitte kann man jemand diesen Titel im ersten Beitrag ändern damit der
> eklatante Rechtschreibfehler behoben wird.

Hab's geändert.

von Daniel A. (daniel-a)


Lesenswert?

Mark B. schrieb:
> Java kennt kein goto

Stimmt, aber dafür gibts benannte Blöcke. In JavaScript übrigens auch.
1
 // Sinnfreier Java/JavaScript code
2
a: {
3
  if(bla())
4
    break a;
5
  bla();
6
}
7
8
i=0;
9
b: do {
10
  while(i<100)
11
    if( i++ == 50 )
12
      continue b;
13
  break;
14
} while(1);

von Michael B. (laberkopp)


Lesenswert?

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.

von steffen (Gast)


Lesenswert?

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.

von MCUA (Gast)


Lesenswert?

>Gleiche Codeteile steckt man üblicherweise in eine eigene Funktion.
Eben nicht! Jedenfalls nicht immer.
Den Grund hatte ich schon genannt.

von M. K. (sylaina)


Lesenswert?

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?

von Zeno (Gast)


Lesenswert?

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

von Zeno (Gast)


Lesenswert?

Daniel A. schrieb:
> Stimmt, aber dafür gibts benannte Blöcke. In JavaScript übrigens auch.

Letztendlich ein goto mit Tarnkappe. :-)

von Herbert P. (Gast)


Lesenswert?

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

von M. K. (sylaina)


Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

@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 ;-)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.