www.mikrocontroller.net

Forum: Compiler & IDEs While(1) - Break und Continue


Autor: ichdu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, ich habe ein Verständnis Problem.

In meinem Code habe ich eine Endlosschleife. Wenn ein bestimmter Zustand 
eintritt, so soll die Schleife bis zum nächsten Schleifendurchlauf nicht 
mehr betrachtet werden. Sowas mach man ja normal mit continue. Ist das 
bei AVR while(1) in einer main anders?

Ich sende an mein Slave Daten, wenn ein CRC Fehler eintritt, so soll 
halt wieder an den Anfang der while-Schleife. Wie gesagt normal macht 
man dies mit continue, aber wenn ich das verwende, bleibt das programm 
hängen. Ändere ich das in break, so läuft das Programm normal.

Aber das ist ja so dann ja garnicht richtig. Oder verstehe ich da was 
falsch?

So sollte es richtig sein (hängt sich auf):
int main(void) {
   while(1) {
      if(rf12_data()) {
         //...
         if(cnt == 255) {
            continue;
         }
      }
   }
}

So läuft das ist aber falsch!:
int main(void) {
   while(1) {
      if(rf12_data()) {
         //...
         if(cnt == 255) {
            break;
         }
      }
   }
}

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Meine Glaskugel meinte, dass "cnt" nicht als volatile deklariert ist.

Autor: Guru (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmm. Üblicherweise benötigst in einer Endlosschleife in main weder break 
noch continue.

Es ist auch unklar woran Du merkst, das das Programm "hängen bleibt". An 
und für sich gibt es das garnicht. Der uC führt immer irgendwas aus.

Ich sehe in Deinem Code nicht die Bedingung "CRC Fehler" reflektiert. 
Deswegen deute ich das hier mal an.
int main(void) {
   while(1) {
      if(rf12_data()) {
         //...
         if(!CRC_Fehler) {
            mach_was_sinnvolles ();
         }
      }
   }
}

Damit wird der Code für den Erfolgsfall eben nur dann ausgeführt, wenn 
alles OK ist, ansonsten einfach zum nächsten Schleifendurchlauf 
übergegangen.

Insgesamt ist Deine Erklärung unklar und es scheint mir, das Du Dir über 
den Ablauf in Kontrollstrukturen nicht klar bist. Wiegesagt ist continue 
und break selten nötig. Ich selbst verwende break nur in switches und 
habe in 30 Jahren noch nie ein continue gebraucht. (Abgesehen von etwas 
komplizierten Fällen in Betriebssystemen). Vor allem möchte ich Dir 
empfehlen das Kapitel hier 
http://openbook.galileocomputing.de/c_von_a_bis_z/...
mal durchzulesen.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ichdu schrieb:
> Ändere ich das in break, so läuft das Programm normal.

In dienem Code sprigst du mit break aus der while(1)-Endlosschleife. 
Danach kommt nichts mehr, also gibt es ein return aus main ins nirwana. 
Das nirwana besteht beim WinAVR aus einer endlosschleife, ergo, der 
Controller "hängt".

Da das aber anscheinend nicht passiert, sind alle weiteren Überlegungen 
müssig, solange du nicht den vollständigen Code zeigst.

Ansonsten hat guru recht - continue braucht man in C noch seltener als 
goto, sprich, nie.

Oliver

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oliver schrieb:
> Ansonsten hat guru recht - continue braucht man in C noch seltener als
> goto, sprich, nie.

Nö. Continue ist durchaus sehr sinnvoll. Selbst in einer Endlosschleife 
kann es sinnvoll sein.

Autor: Nico Sch. (nico22)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oliver schrieb:
> Ansonsten hat guru recht - continue braucht man in C noch seltener als
> goto, sprich, nie.

Brr, da würd mir dann aber was fehlen ohne Continue.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guru schrieb:
> Hmm. Üblicherweise benötigst in einer Endlosschleife in main weder break
> noch continue.

Rufus Τ. Firefly schrieb:
> Nö. Continue ist durchaus sehr sinnvoll. Selbst in einer Endlosschleife
> kann es sinnvoll sein.

Nico Sch. schrieb:
> Brr, da würd mir dann aber was fehlen ohne Continue.

Nun denn, drei Programmierer, vier Meinungen ;)
Ich bleib bei meiner ;)

Oliver

Autor: U.R. Schmitt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vieleicht sollte man verstehen was break und continue überhaupt macht.
ichdu weiß es wohl nicht, oliver wohl auch nicht so genau.

break springt aus einer Schleife raus egal of while for do ... while, 
das heisst die Schleife (bzw. bei mehreren geschachtelten die innerste 
Schleife) wird sofort verlassen. Das ist wie ein goto hinter das 
Schleifenende

continue springt sofort wieder an den Anfang der Schleife, bei einer for 
Schleife führt das dazu, daß die incrementbedingung ausgeführt wird. Das 
ist genau dann sinnvoll, wenn ich den rest des codes in der Schleife 
nicht mehr ausführen will.
Beispiel
do (hole nächste Zeile aus Konfigurationsdatei) {
  if (ist Kommentar) continue;
  verarbeite zeile
  ...
} (while nicht dateiende Konfigurationsdatei)

Oliver und jetzt erzähle nicht da könnte man if else benutzen, wenn du 
mehrere Abbruchbedingungen für die Verarbeitung der aktuellen zeile hast 
ist continue deutlich besser, eleganter, verständlicher.

Autor: U.R. Schmitt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
U.R. Schmitt schrieb:
> liver und jetzt erzähle nicht da könnte man if else benutzen, wenn du
> mehrere Abbruchbedingungen für die Verarbeitung der aktuellen zeile hast
> ist continue deutlich besser, eleganter, verständlicher.
und auch schneller und kleiner weil keine else Zweige ausgewertet werden 
müssen.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
U.R. Schmitt schrieb:
> ichdu weiß es wohl nicht, oliver wohl auch nicht so genau.

Danke, ich weiß das schon sehr genau. Und bin in meinem Leben bisher 
ohne continue ausgekonnen. Bei brak ist das anders, das nutze ich ab und 
an 8ausserhaöb von switch).

U.R. Schmitt schrieb:
> Oliver und jetzt erzähle nicht da könnte man if else benutzen,

Es gibt IMMER mehrere Wege nach Rom, und die wenigsten führen über 
continue.

Oliver

Autor: U.R. Schmitt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oliver schrieb:
> Es gibt IMMER mehrere Wege nach Rom, und die wenigsten führen über
> continue.
ROFL!
Eben, weil die meisten Wege nach Rom Umwege sind!
Es gibt in der Regel nur einen schnellsten und einen kürzesten aber 
viele andere, aber du darfst gerne erst nach Frankreich fahren, dort die 
Fähre nach Korsika nehmen und dort dann ne andere zum italienischen 
Festland. dann ist es nicht mehr weit nach Rom, ist bestimmt ne schöne 
Fahrt :-)

Merke: nur wer möglichst viele Wege kennt und bereit ist diese auch zu 
benutzen hat eine größere Chanche den für das Projekt besten Weg zu 
finden.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
U.R. Schmitt schrieb:

> Merke: nur wer möglichst viele Wege kennt und bereit ist diese auch zu
> benutzen hat eine größere Chanche den für das Projekt besten Weg zu
> finden.

Wobei man den besten Weg getrost nach der Ästhetik wählen kann.  Der
compiler wird für mehrere verschieden hingeschriebene Bedingungen oft
genug den gleichen Code ausspucken.

Die Diskussion erinnert mich irgendwie an Donald E. Knuth's Aufsatz:
"Structured Programming with GOTOs".

Autor: U.R. Schmitt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jörg Wunsch schrieb:
> Wobei man den besten Weg getrost nach der Ästhetik wählen kann.  Der
> compiler wird für mehrere verschieden hingeschriebene Bedingungen oft
> genug den gleichen Code ausspucken.
Das bezweifle ich zumindest für den Fall daß du eine Schleife mit einem 
komplexeren Lnnenleben hast bei dem du sonst ein mehrfaches Abfragen 
nach irgendwelchen Stati machen müsstest, wenn du kein continue benutzen 
würdest.
Wobei man jetzt wieder sagen kann schlecht designt wenn der Code in der 
Schleife so komplex ist ....
Egal, aber wenn man sagt ich brauche kein continue und kein break, dann 
kann man genau so sagen, mir reicht ein do ... while, die while und for 
Schleifen sind vollkommen unnötig, das kann ich alles mit do ... while 
machen.

Jörg Wunsch schrieb:
> Die Diskussion erinnert mich irgendwie an Donald E. Knuth's Aufsatz:
> "Structured Programming with GOTOs".
den kenn ich jetzt leider nicht, aber das Dauerstreitthema goto sind 
"schlecht" / "doch manchmal notwendig" zeigt auch daß Dogmen meistens 
nicht zielführend sind.
ich habe Ablaufcode gesehen wo jeder Aufruf immer ein "if (rc==0) ..." 
hatte, die hätten mit einem goto ERROR besser ausgesehen.
Egal wer nur ein Subset der Befehle nutzen will soll das gerne tun, wie 
gesagt es gibt mehrere Wege...

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
U.R. Schmitt schrieb:
> den kenn ich jetzt leider nicht, aber das Dauerstreitthema goto sind
> "schlecht" / "doch manchmal notwendig" zeigt auch daß Dogmen meistens
> nicht zielführend sind.

Die Diskussion ist so alt wie die Programmier-Menschheit, und wird auch 
immer fortbestehen. Der oben genannte Artikel stammt von 1974, und ist 
insofern sicherlich richtig, als daß in den nach diesem Zeitpunkt 
entwickelten höheren Programmiersprachen (also eigentlich fast allen...) 
Strukturen zum "verdeckten" Einsatz von goto enthalten sind, wie 
setjmp/longjmp, try/catch, die doch sehr viel angenehmeres Programmieren 
zulassen, als es mit einer Programmiersprache der "reinen Lehre" wie 
Niclaos' Wirthschen Pascal oder Modula der Fall wäre.

Um aber wieder aufs Thema zurückzukommen:

Das der Code des Threadstartes nicht funktioniert, liegt weder an 
continue noch an break.
Vielleicht meldet der sich ja nochmal mit dem vollständigen Code.

Oliver

Autor: U.R. Schmitt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oliver schrieb:
> Das der Code des Threadstartes nicht funktioniert, liegt weder an
> continue noch an break.
> Vielleicht meldet der sich ja nochmal mit dem vollständigen Code.
Da stimme ich dir zu, insofern nichts für ungut :-)
Wenn man wie der TO zur Fehlersuche einfach ein continue durch ein break 
ersetzt, dann möchte ich hier mal Karl Heinz ziteren: "Er braucht 
dringend ein C Buch". -und sollte natürlich auch lesen-

Autor: DirkB (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ein break die Funktion erfüllt, hat er noch eine Schleife in dem 
//...

Autor: Guru (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ui. Da habe ich aber was angerichtet!

Es lag nicht in meiner Absicht Dogmen aufzustellen. Ich bin auch der 
Meinung, dass meine Äusserungen:

" Üblicherweise benötigst in einer Endlosschleife in main weder break
noch continue."

und:

"Wiegesagt ist continue und break selten nötig."

nicht als Dogmen zu verstehen sind, die man relativieren muss.

Und mit:

"Ich selbst verwende break nur in switches und habe in 30 Jahren noch 
nie ein continue gebraucht. (Abgesehen von etwas komplizierten Fällen in 
Betriebssystemen)."

habe ich eingeräumt, dass auch ich Gründe kenne, break und continue 
anzuwenden. (Klar. Bei Switch ist das trivial und man kommt nur mit 
Gewalt drum herum).

Wenn ich mir die Beiträge so anschaue so scheint sich jeder der 
Antwortenden zumindest grundsätzlich darüber klar zu sein, dass und wie 
man ein continue vermeiden kann. Irgendwie kommt dann auch immer die 
Ästhetik ins Spiel. Das aber sollte man ernst nehmen, denke ich, und 
hier deswegen keine "Klarstellungen" anfügen. Das man über Geschmack 
streiten kann, ob eine ausformulierte Bedingung mit ausformulierten 
else-if Zweigen nun "schöner" ist, als ein continue, muss letztlich 
jeder selbst entscheiden.

Warum schreibe ich das hier keine Klarstellungen nötig sind?
Nun, weil der TO ganz offensichtlich die Grundlagen nicht beherrscht und 
erstmal überhaupt lernen muss wie while-Schleifen und insbesondere 
unendliche while-Schleifen zu behandeln hat. Insofern waren meine 
relativ formulierte Abweisung von continue und break, meine ich, 
durchaus sinnvoll.
Mit den ganzen Gründen warum und wann continue sinnvoll ist, kann er 
nach meiner Wahrnehmung garnichts anfangen.

Wenn der TO klare Gründe gebracht hätte warum er nun ein continue 
verwenden will, zu erkennen gegeben hätte, das er den anderen Weg kennt 
und nur einen Kommentar dazu gewünscht hätte, was davon zu halten sei, 
das er continue anwendet, wäre das ein anderer Fall gewesen, den ich, 
unter Umständen mit einem Vorbehalt, aber letztlich bejahend beantworten 
hätte müssen.
Wenn er z.B. hätte darlegen können das die Abprüfung von 
Alternativbedingungen notwendig sehr viel Zeit braucht und sein Programm 
zeitkritisch ist, wäre ja gegen continue nichts zu sagen gewesen. 
(Übrigens einer der Fälle z.B. in Betriebssystemen wo ich es auch 
verwenden würde).

Naja. Es fehlt uns jedenfalls eine klare Erklärung des TO zu dem 
Problem, denke ich und einiges an Grundlagenkenntnissen könnte er auch 
noch nachlesen. Bei dem Satz "... so soll die Schleife bis zum nächsten 
Schleifendurchlauf nicht mehr betrachtet werden." hat sich mir doch 
irgendwie was innerlich verwunden. Der uC gibt sich doch keinen 
"Betrachtungen" hin. :-)

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Diskussion geht vollkommen am Kern vorbei.

Schleifen verlässt man prinzipiell mit longjmp(), das ist
portabel und macht mehr Eindruck.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus Wachtler schrieb:

> Schleifen verlässt man prinzipiell mit longjmp(), das ist
> portabel und macht mehr Eindruck.

Ach was!  Man lässt einen watchdog reset zuschlagen, und wenn man
sich noch irgendwie den vorherigen Zustand merken muss, dann organi-
siert man sich das über eine .noinit-Variable.

Alternativ: man patcht die Einsprungadresse für den nächsten Start
nach dem Reset in die Vektortabelle ... selbstmodifizierender Code,
war zu Z80-Zeiten gang und gäbe. :-))

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.