Was ist der Zweck von ";" am Ende der for-Schleife?

76

Ich habe folgenden Code gefunden:

Der Funktionspunkt besteht darin, zu überprüfen, ob eine Zahl eine Primzahl ist oder nicht.

Ich verstehe nicht, warum die for-Schleife ;am Ende hat:

Ohne das funktioniert der Code nicht richtig.

Was ist die Erklärung?

Wien95
quelle
48
Die for-Schleife hat am Ende ein Semikolon, weil der Autor EVIL ist! In solchen Situationen sollte es auf seine eigene Linie gehen.
sh1
21
@ sh1 Oder, wenn der Autor die gesamte Schleife in einer Zeile haben möchte { }, kann anstelle von ;dokumentiert werden, dass die Schleife einen leeren Körper haben soll und keine der nachfolgenden Zeilen enthält.
Eliah Kagan
22
@EliahKagan, manchmal, wenn ich das Gefühl habe, die Leere des Schleifenkörpers betonen zu wollen, schreibe ich for (...) continue;.
sh1
8
@coredump Aber die beiden Probleme mit dem auf diese Weise verwendeten Semikolon sind (1), dass es wie ein Fehler aussieht, den ein wohlmeinender Entwickler eines Tages entfernen könnte; und (2) wenn Sie es nicht sehen, erwarten Sie, dass die Anweisung darunter diejenige ist, die "geloopt" ist. Letzteres ist eine besondere Gefahr, da Programmierer lernen, das Semikolon am Ende einer Zeile nicht besonders zu beachten. So wie Menschen, die lesen, nicht bemerken, wenn ein Satz nicht mit einem
Punkt
6
@ Marco13 Warum automatisch annehmen, dass der ursprüngliche Autor unwissend ist? Sie hassen diese Art des Schreibens sehr gut. Aber Sie werden viele Leute finden, die den forLoop-Ansatz bevorzugen : Schließlich gibt es eine Initialisierung, eine Stoppbedingung und eine Iteration, die natürlich durch das forKonstrukt ausgedrückt wird . Sie sind anderer Meinung, aber ich bin sicher, der Autor weiß, was eine whileSchleife ist. Übrigens, deshalb brauchen Sie Codierungskonventionen in einem Team.
Coredump

Antworten:

89

Es bedeutet genau das Gleiche wie:

MM
quelle
7
Und dies ist eine viel bessere Möglichkeit, einen leeren Schleifenkörper zu schreiben (obwohl das Schreiben {}in einer einzelnen Zeile möglicherweise ein visuell einfacherer Hinweis auf einen leeren Körper ist). Ohne Legacy-Code wäre die Sprache ohne die ;Regel für leere Anweisungen besser geeignet . Das ;, was danach obligatorisch do ... while(...)ist, ist auch dumm, aber zumindest dort habe ich eine kluge Verwendung davon gesehen.
Marc van Leeuwen
5
@MarcvanLeeuwen finde ich ;besser lesbar. Der leere Block sieht aus wie ein Unfall, als hätte der Programmierer einfach vergessen, den Körper auszufüllen. Die leere Aussage macht seine Absichten klar.
Paul
19
@Paulpro, ich finde, dass beide potenzielle Fehler sind und for (...) { /* empty block */ }klarer als beide, soweit dies zeigt, dass es beabsichtigt ist.
Atk
2
Ich bin kein CProgrammierer, aber warum um alles in der Welt sollte dies jemals nützlich sein?
Ethan Bierlein
6
@EthanBierlein die 'Arbeit' wird durch die Anweisungen in der erledigt ( ); Der Punkt dieser Schleife ist es count, einen bestimmten Wert zu haben, der aufzahl
MM
53

Eine for-Schleife hat das forSchlüsselwort, gefolgt von Klammern mit drei optionalen Ausdrücken, die durch Semikolons getrennt sind, gefolgt von einem Textkörper, der in jeder Iteration der Schleife ausgeführt wird.

Das Ziel der for-Schleife in Ihrem Beispiel besteht darin, den Wert von countfestzulegen, mit dem zahlin der folgenden if-Anweisung verglichen wird . Dies wird in den durch Semikolons getrennten Ausdrücken erreicht, sodass der Schleifenkörper nichts tun muss.

Da die Schleife nichts tun muss, verwendet sie die leere Anweisung als Hauptteil.

Wenn das ;am Ende weggelassen würde und keine anderen Änderungen vorgenommen würden, würde die if-Anweisung nach der for-Schleife selbst zum Hauptteil der for-Schleife. (Das ist nicht beabsichtigt und würde das Programm brechen, wie Sie beobachtet haben.)

Es ;ist jedoch nicht die einzige Möglichkeit, einen leeren Schleifenkörper zu schreiben, und es ist wahrscheinlich auch nicht die sinnvollste Möglichkeit , einen eigenen Schleifenkörper aus einer einzelnen Zeile in derselben Zeile zu machen. Es funktioniert einwandfrei, aber das Problem ist, dass andere Leser - und vielleicht derselbe Programmierer, der später zum Projekt zurückkehrt - sich fragen, ob es tatsächlich ein Fehler war. Schließlich gibt man beim Codieren in einer Sprache im C-Stil häufig Semikolons an den Zeilenenden ein, sodass es einfach ist, ein zusätzliches Semikolon einzugeben, wenn es nicht dazu gehört.

Das andere Problem ist , dass im Code , in dem eine einzeilige Schleife mit ;als sein Körper ist der gewählte Stil, ist es schwer zu erkennen , wenn jemand tatsächlich hat den Fehler , Putting a gemacht , ;wenn man nicht gehört.

Daher können diese Alternativen vorzuziehen sein:

  • Setzen Sie das ;eingerückte Zeichen in die nächste Zeile - wie sh1 vorschlägt
  • Schreiben des Schleifenkörpers als leerer Block { }und nicht als leere Anweisung
  • Machen Sie den Schleifenkörper zu einer continue;Anweisung, die einfach bewirkt, dass die Schleife zur nächsten Iteration übergeht (was dasselbe ist, was passiert, wenn der Schleifenkörper leer ist) - auch wie sh1 vorschlägt
Eliah Kagan
quelle
4
Während ich dem ;und dem zustimmen kann {}, würde ich das continue;extrem seltsam finden. Es würde für mich so aussehen, als hätte jemand continueeine äußere Schleife oder so erwartet . Auf jeden Fall ein WTF-Moment, und Sie möchten diese im Code vermeiden. Ich würde sagen, {}erfasst die Absicht auf die am besten lesbare Weise.
Angew ist nicht mehr stolz auf SO
5
Eine andere Option (die mit den anderen kombiniert werden kann) besteht darin, einen Kommentar einzufügen : for (...) /* do nothing */ ;, um deutlich zu machen, dass dies beabsichtigt ist.
2
Ich würde zu den Alternativen hinzufügen, die die Variable innerhalb der Schleife erhöhen , wie:for(count=2; zahl % count != 0 && zahl >= count;) ++count;
Massa
3
@Massa - Die forSchleife wird per Definition gezählt. Das Exportieren des Inkrementors aus der Schleife gibt Ihnen keinen Grund, forvs whilezu verwenden.
@ vaxquis Sie haben noch die Initialisierung; Ich wäre int count = 2; while( zahl % count && zahl >= count ) ++count;sowieso
Massa
41

Das Semikolon am Ende der for-Schleife bedeutet, dass es keinen Körper hat. Ohne dieses Semikolon glaubt C, dass die ifAnweisung der Hauptteil der for-Schleife ist.

Rohn Adams
quelle
4
+ int (PI / 3), um genau zu sein, ohne in die Debatte "Ist es eine gute / schlechte Codierungspraxis" einzusteigen.
Auf jeden Fall +1, eine saubere, kurze sachliche Antwort, die nicht versucht, den Code als schlecht oder schlecht zu deklarieren.
Vality
1
Die for-Schleife hat definitiv einen Körper. Es ist nur so, dass der Körper nur aus der Null-Anweisung besteht ;. Ein Einzelner ;ist praktisch (wenn nicht tatsächlich) an jedem Ort gültig, an dem eine Anweisung zulässig ist, da ein Einzelgänger eine Nullanweisung ;ist (was eine Anweisung ist).
Benutzer
22

Die Syntax der forSchleife ( Iterationsanweisung ) lautet

statementkann eine Null-Anweisung sein ( ;). C11 6.8.3 sagt

Eine Null-Anweisung (die nur aus einem Semikolon besteht) führt keine Operationen aus.

In Absatz 5 gibt es ein Beispiel

Im Programmfragment

Eine Null-Anweisung wird verwendet, um der Iterationsanweisung einen leeren Schleifenkörper bereitzustellen .

Das Gleiche passiert in

;wird verwendet, um der forAnweisung einen leeren Schleifenkörper bereitzustellen. Ohne ;die Anweisung neben der forSchleife wird als ihr Körper betrachtet und ausgeführt.

Haccks
quelle
1
+ int (PI / 3), um genau zu sein, ohne in die Debatte "Ist es eine gute / schlechte Codierungspraxis" einzusteigen.
@ vaxquis; Ja, denn die Frage lautet: "Warum hat die for-Schleife ;am Ende?" . Es geht nicht darum, "ob es eine gute Übung ist oder nicht?" .
Haccks
17

Zusätzlich zu dem, was die anderen ausgezeichneten Antworten bereits sagen, möchte ich darauf hinweisen

(dh eine forSchleife mit einer leeren Anweisung, die zum Inkrementieren eines "Zählers" verwendet wird) entspricht

Dies würde das Ziel des Codes noch klarer machen als einige der aufgeführten Alternativen: Wenn keine Kommentare vorhanden sind, wie im vorliegenden Fall, könnte eine Schleife mit einer leeren Anweisung einen anderen Programmierer verwirren, der den Code beibehalten oder verwenden muss (wie er war) der Fall mit dem OP hier).

Der Kontext kann helfen, den wahren Umfang der Anweisung zu erkennen, aber zwischen einer forSchleife mit einer leeren Anweisung und einer whileSchleife mit einer Anweisung erfordert letztere weniger Arbeit, um ihren Umfang zu verstehen.

Federico
quelle
1
Minor nitpick: Dies ist nicht unbedingt gleichwertig, da in der zweiten Version countin einem größeren Umfang deklariert wird.
Coredump
Ich meine, im Allgemeinen ... hier countwird in beiden Versionen am Anfang der Funktion deklariert.
Coredump
2
@coredump: In Anbetracht dessen, dass der Zweck dieser Schleife - in diesem speziellen Fall - darin besteht, countden richtigen Wert zu erhalten, damit sie weiter verwendet werden kann, countmuss sie in einem größeren Umfang vorhanden sein, damit dies überhaupt funktioniert und deshalb ist es genau gleichwertig. (Es ist jedoch immer noch ein hässlicher Missbrauch einer forSchleife, und Federico hat Recht, dass dies der richtige Weg ist, um die Semantik auszudrücken.)
Mason Wheeler
@ MasonWheeler Ja, ich habe über den allgemeinen Fall nachgedacht. Beide sind hier tatsächlich gleichwertig.
Coredump
1
Warum ist die for-Schleife unklar? Ich habe verstanden, dass eine for-Schleife explizit vorhanden war, um eine Initialisierung, eine Bedingung und eine iterierende Anweisung logisch zu bündeln. Es ist nie notwendig, eine for-Schleife zu verwenden, aber dieser Fall schien vernünftig und sauber geschrieben zu sein.
Vality
12

Das ;Nach der forSchleife bedeutet einfach, dass die forSchleife nichts weiter tut, als den Zähler zu erhöhen count.


quelle
12

forAussage :

Die for-Anweisung ist eine Schleifenanweisung, deren Struktur eine einfache Initialisierung von Variablen, Ausdruckstests und Variablenmodifikationen ermöglicht. Es ist sehr praktisch, um gegengesteuerte Schleifen herzustellen. Hier ist die allgemeine Form der for-Anweisung:

[...]

Null-Anweisung :

Die Null-Anweisung ist lediglich ein Semikolon.

Eine Null-Anweisung macht nichts. Es wird nirgendwo ein Wert gespeichert. Während der Ausführung Ihres Programms vergeht keine Zeit.

Am häufigsten wird eine Null-Anweisung als Hauptteil einer Schleifenanweisung oder als einer oder mehrere der Ausdrücke in einer for-Anweisung verwendet. Hier ist ein Beispiel für eine for-Anweisung, die die null-Anweisung als Hauptteil der Schleife verwendet (und aus Spaß auch die ganzzahlige Quadratwurzel von n berechnet):

Hier ist ein weiteres Beispiel, das die null-Anweisung als Hauptteil einer for-Schleife verwendet und auch eine Ausgabe erzeugt:

Manchmal wird auch eine Null-Anweisung verwendet, um einer Bezeichnung zu folgen, die ansonsten das Letzte in einem Block wäre.


In Ihrem Fall ;ist dies die Null-Anweisung der forAnweisung :

Ohne sie wird das ifzur for-Anweisung:

Daher anders verhalten.

Falsarella
quelle
1
Schön aus der Dokumentation zitiert. +1
Vality
10

Die for-Schleife dient nur dazu, den Wert von zu erhöhen count.

bmpasini
quelle
9

Eine forSchleife hat (normalerweise) einen Körper.

wo der Körper in Klammern eingeschlossen ist { }

Für einen einzelnen Anweisungshauptteil sind die geschweiften Klammern jedoch optional.

; ist eine leere Aussage.

Der obige Kombinieren es wird offensichtlich , dass die forSchleife ausführt , bis die Bedingung wird false.

user3629249
quelle
6

Die for-Schleife durchläuft im Grunde alle Zahlen, die kleiner oder gleich, zahlaber größer als 2 sind, und speichert sie in der Variablen count. Während es all diese Zahlen durchläuft, prüft es, ob zahles durch teilbar ist count. Wenn zahldurch teilbar ist count, wird die Schleife gestoppt. Andernfalls wird die Schleife gestoppt, wenn sie countgleich ist zahl.

Die if-Anweisung nach der for-Schleife prüft, ob countgleich ist zahl. Wenn zahldies der Fall zahlist , muss dies bedeuten, dass die Schleife alle Zahlen kleiner und größer als 2 durchlaufen hat . Dies bedeutet, dass sie durch alle Zahlen kleiner als sie selbst und größer 2 teilbar ist, was zahlPrimzahlen ergibt .

As
quelle
0

Es gibt die Anweisung an, für die die for-Schleife verwendet wird. Es kann nicht leer sein. Zumindest sollte es eine einzige Aussage enthalten. ;; ist die leere Anweisung, für die die Iteration durchgeführt wird.

hamidi
quelle