Im Anhang ist mein kläglicher Versuch, ankommende Daten(Strings) in ein Array zu schreiben. Ich arbeite mit einem Wiznet 5300. Senden klappt, nur das Reinschreiben der FIFO-Daten(Empfangen) scheitert daran die Daten aus dem FIFO byteweise und sinnvoll ins interne Memory vom Wiznet zu schreiben. Der FIFO muss immer 16-Bit-weise ausgelesen werden, deswegen temp0 und temp1. Die n +16-Gesichte soll die Bytes aneinanderschieben. Kann mir jemand einen Hinweis geben? (bitte keine "hier ist ein tutorial"-links). Es hakt bei payload = ((temp0<<m)+((temp1)<<n));
Frischling schrieb: > Im Anhang ist mein kläglicher Versuch, ankommende Daten(Strings) in ein > Array zu schreiben. Da ist schon mal das erste Problem. Woher weißt du, wann der String zu Ende ist? *payload kann ja wohl nicht die Steuerung der Schleife übernehmen, denn in payload kommt ja das Ergebnis rein. Wie willst du daber das Ergebnis befragen, wenn du die Werte noch gar nicht hast? Das kann also so nicht stimmen. Zum zweiten ist payload ein Array. Man kann damit natürlich über Pointer-Syntax zugreifen. Aber eigentlich ist das recht witzlos. WEnn etwas ein Array ist, dann behandle es auch als Array - ok, nicht immer, aber an dieser Stelle ist es ganz sicher die einfachste Variante. Mach dir eine index-Variable, mit der indizierst du in das Array payload[index] = .... und erhöhst den index nach jedem Zeichen. Man muss das nicht komplizierter machen als notwendig. > Es hakt bei payload = ((temp0<<m)+((temp1)<<n)); Darüber breiten wir mal den Mantel des Schweigens. Das ist auf so vielen Ebenen falsch, dass es mit dem Hinweis auf ein Tutorial nicht getan wäre. Benutze Array-Index-Syntax wenn du mit Pointern auf Kriegsfuss stehst und das Problem ist keines mehr.
Quelltext als in einer PDF-Datei versteckten Screenshotausschnitt unterzubringen ist eine ganz tolle Idee. Im übrigen ist auch die Bestimmung der Größe von "payload"
1 | datasize = (udphead & 0xFF000000); |
2 | char payload [datasize]; |
ganz sicher nicht das, was Du erreichen willst. Damit ist nämlich payload entweder 0 oder aber mindestens 16 MBytes groß.
Tu dir selbst einen Gefallen und streich das
1 | goto
|
Wenn du ein goto brauchst, dann stimmt was mit deiner Programmstruktur nicht! Meiner Meinung nach gibt es nur drei Einsatzgebiete für goto: 1. Kernel-Programmierung (da ist es sogar erwünscht!) 2. Assembler 3. Windows Batch-Scripte In allen sonstigen Anwendungsfällen hat goto nichts zu suchen, es sei denn, du legst keinerlei Wert auf strukturierte Programmierung. Grüße
Kaj schrieb: > Tu dir selbst einen Gefallen und streich dasgoto > > Wenn du ein goto brauchst, dann stimmt was mit deiner Programmstruktur > nicht! > > Meiner Meinung nach gibt es nur drei Einsatzgebiete für goto: > 1. Kernel-Programmierung (da ist es sogar erwünscht!) Und was macht der Kernel so besonderes mit goto, das deiner Meinung nach niemals je einem anderen C-Programm nützlich sein könnte? > In allen sonstigen Anwendungsfällen hat goto nichts zu suchen, es sei > denn, du legst keinerlei Wert auf strukturierte Programmierung. Es gibt schon sinnvolle Einsatzmöglichkeiten, gerade um den Code besser zu strukturieren. Das sind aber nicht viele. Im Prinzip nur zwei: Fehlerhandling und die Möglichkeit aus einer Schleife mehr als eine Ebene rauszuspringen, da break leider immer nur eine Ebene weit geht.
Rolf Magnus schrieb: > gerade um den Code besser > zu strukturieren Rolf Magnus schrieb: > die Möglichkeit aus einer Schleife mehr als eine > Ebene rauszuspringen Und du kannst nicht nur über mehrere Schleifenebenen springen... Mit goto hast du die absolut wunderbare Möglichkeit einen Mischmasch aus PAP, NSD und sonstwas zu schaffen. Tolle strukturierung ;) Rolf Magnus schrieb: > Und was macht der Kernel so besonderes mit goto, das deiner Meinung nach > niemals je einem anderen C-Programm nützlich sein könnte? In der (Linux-) Kernel- und Treiberprogrammierung wird mehr Wert auf performanten Code gelegt. Beispiel: Ein Treiber fordert Speicher für drei Variablen an. Wenn das alozieren von Speicher für nur eine Variable scheitert, muss der Vorgang abgebrochen und der bereits gewährte Speicher wieder freigegeben werden.
1 | // ohne goto
|
2 | if(register_chardev(...)not failed) |
3 | {
|
4 | if(request_region(...) failed) |
5 | {
|
6 | unregister_chardevv(...); |
7 | return -EIO; |
8 | }
|
9 | if(request_irq(...) failed) |
10 | {
|
11 | free_region(...); |
12 | unregister_chardev(...); |
13 | return -EIO; |
14 | }
|
15 | return 0; //success |
16 | }
|
17 | return -EIO; |
18 | |
19 | //gleicher code mit goto
|
20 | if(register_chardev(...) not failed) |
21 | {
|
22 | if(request_region(...) failed) |
23 | goto out_region; |
24 | if(request_irq(...) failed) |
25 | goto out_irq |
26 | return 0; //success |
27 | }
|
28 | else
|
29 | {
|
30 | goto out; |
31 | }
|
32 | out_irq: |
33 | free_region(...); |
34 | out_region: |
35 | unregister_chardev(...); |
36 | out: |
37 | return -EIO; |
Das ist (abgesehen von den weggelassenen argumenten) orginal code aus dem linux-kernel / linux-treibern. Natürlich ist es wieder eine Frage der eigenen Überzeugung: goto or not goto, thats the question. Aber ich sehe es mal so: Es gibt mind. einen verdammt guten Grund, weshalb goto so verrufen ist: Spaghetti-Code lässt grüßen! ;) Wer es schaft mit goto wirklich gut und sauber strukturierten code zu schreiben, an dem dann auch mehrere andere Programmiere nichts auszusetzen haben, vor dem ziehe ich meinen Hut! (Auch wenn ich mir dann erst einen Hut kaufen muss :D ) Allerdings dürfte das auf die wenigsten Programmiere zutreffen. Grüße
Kaj schrieb: > Rolf Magnus schrieb: >> die Möglichkeit aus einer Schleife mehr als eine >> Ebene rauszuspringen > > Und du kannst nicht nur über mehrere Schleifenebenen springen... > Mit goto hast du die absolut wunderbare Möglichkeit einen Mischmasch aus > PAP, NSD und sonstwas zu schaffen. Tolle strukturierung ;) Daß man das kann habe ich nie bestritten. Mit vielen Sprachmitteln kann man Unsinn treiben. Deshalb muß man sie aber nicht gleich komplett verbannen. Man kann auch mit einem Hammer jemandem den Schädel einschlagen, und trotzdem wird er gerne und erfolgreich genutzt, um Nägel in Wände zu bekomnmen. > Rolf Magnus schrieb: >> Und was macht der Kernel so besonderes mit goto, das deiner Meinung nach >> niemals je einem anderen C-Programm nützlich sein könnte? > > In der (Linux-) Kernel- und Treiberprogrammierung wird mehr Wert auf > performanten Code gelegt. > > Beispiel: > Ein Treiber fordert Speicher für drei Variablen an. Wenn das alozieren > von Speicher für nur eine Variable scheitert, muss der Vorgang > abgebrochen und der bereits gewährte Speicher wieder freigegeben werden. Exakt das meinte ich mit der Fehlerbehandlung, bei der goto nützlich ist. Das ist es aber auch außerhalb des Kernels, und zwar nicht primär aus Gründen der Peformanz, sondern der Übersichtlichkeit. Variante 1 deines Beispiels beinhaltet Code-Duplizierung, die sehr fehleranfällig ist. Außerdem ist die Fehlerbehandlung kreuz und quer mit dem Code vermischt, während sie bei der goto-Variante schön sauber getrennt ist. Ich empfinde das durchaus als besser strukturiert. > Wer es schaft mit goto wirklich gut und sauber strukturierten code zu > schreiben, an dem dann auch mehrere andere Programmiere nichts > auszusetzen haben, vor dem ziehe ich meinen Hut! (Auch wenn ich mir dann > erst einen Hut kaufen muss :D ) > Allerdings dürfte das auf die wenigsten Programmiere zutreffen. Eigentlich ist es gar nicht so schwer. Es ist halt nur noch leichter, mit goto Spaghetti-Code zu schreiben. ;-)
Rolf Magnus schrieb: > Es ist halt nur noch leichter, > mit goto Spaghetti-Code zu schreiben. ;-) Genau deswegen ist es ja auch so verrufen ;) Ich lass aufjedenfall meine fingerchen von goto, weil es auch ohne sehr gut geht... und weil mich jeder Programmierer den ich kenne für den einsatz von goto verprügeln würde. :D Wenn ich an einer Stelle bin, wo ich mir denke "ach, ein goto wäre eigentlich ganz schön...", dann überdenk ich nochmal meine Programmstruktur, baue um, und dann geht es auch ohne goto. Spätestens wenn noch andere auf den Code gucken oder damit arbeiten müssen, hat sich das schon so gut wie erledigt. Und da gibt es noch mehr Beispiele an Programmierpraktiken (in C/C++) die zwar ganz toll sind, aber nicht effektiv angewand werden können, weil mehr als nur eine Person mit dem Code arbeiten muss. Aber wie ich oben schon geschrieben habe: > Natürlich ist es wieder eine Frage der eigenen Überzeugung: > goto or not goto, thats the question. So schön die Vorzüge auch sind, das K.O.-Kriterium "Spaghetti-Code" überwiegt meiner Meinung einfach. An den TO: Ein bisschen mehr code als nur der Screenshot-Schnipsel wäre schon hilfreich. In diesem Sinne, schönen Mittwoch Grüße
Kaj schrieb: > Ich lass aufjedenfall meine fingerchen von goto, weil es auch ohne sehr > gut geht... aber nur, weil die freundlichen Sprachdesigner die gotos per setjmp/lonjmp oder im OOP per try/catch verstecken. Ohne geht es halt nicht immer. Oliver
Nichts desto trotz würde ich den Rat an einen Anfänger unterschreiben, die Finger von goto zu lassen. Das die Könner goto sinnvoll einsetzen können, wird wohl niemand abstreiten. Ein Anfänger ist aber kein Könner. Dafür setzen Anfänger einen goto für alles mögliche ein, wo ein goto sicher nicht sinnvoll ist.
Kaj schrieb: > Meiner Meinung nach gibt es nur drei Einsatzgebiete für goto: > 1. Kernel-Programmierung (da ist es sogar erwünscht!) > 2. Assembler > 3. Windows Batch-Scripte und 4. Generierter Code Beispielsweise verwendet GCC goto in auto-generiertem C-Code, der während des GCC-Builds aus Maschinenbeschreibungen (md) erzeugt wird. Ansonsten sähe man da Verschachtelungstiefen von mehreren 100 oder gar 1000 if-then-else. Hier ein Beispiel für eine solche Datei mit ca 70000 Zeilen: http://www.open64.net/doc/d3/d30/kg_09_09fe_2gnu_2i386_2insn-recog_8c-source.html Zudem macht goto die Wiederverwendung von Code-Blöcken einfacher, beispielsweise in
1 | if (a) |
2 | {
|
3 | if (b) |
4 | BLOCK1; |
5 | else
|
6 | BLOCK2; |
7 | }
|
8 | else if (c) |
9 | BLOCK2; |
Zwar kann man das mehrfache Auftauchen von Blöcken (hier BLOCK2) durch Umformulierung der if-Bedingungen vermeiden, dadurch werden aber die if-Bedingungen komplizierter, und es müssen mehrfach ähnliche Teilausdrücke in den if-Abfragen getätigt werden. Für das kleine Beispiel ist die Umformulierung zwar einfach, für die große, verlinkte Datei ist eine Umformulierung aber weder zielführend noch hilfreich. goto ist dort eindeutig die beste und überlegen Lösung.
Johann L. schrieb: > 4. Generierter Code Naja, meine Aussage war auf "handgeschriebenen" code bezogen. ;) Grüße
Karl Heinz schrieb: > Nichts desto trotz würde ich den Rat an einen Anfänger unterschreiben, > die Finger von goto zu lassen. > > Das die Könner goto sinnvoll einsetzen können, wird wohl niemand > abstreiten. Ein Anfänger ist aber kein Könner. Dafür setzen Anfänger > einen goto für alles mögliche ein, wo ein goto sicher nicht sinnvoll > ist. Sehe ich auch so. So wird's aber meist nicht verkauft, sondern eher so: Goto entstammt der Hölle und wurde vom Teufel geschickt, um deinen Code zu zerstören, also setze es blos niemals im Leben ein. Deshalb haben auch die meisten Könner panische Angst vor goto, wie man ja hier ganz gut sehen kann.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.