Was ist der Zweck von “;” am Ende der for-Schleife?
Lesezeit: 11 Minuten
Wien95
Ich habe folgenden Code gefunden:
int func_prim (int zahl) {
int count;
if (zahl < 0)
return -1;
for (count = 2; zahl % count != 0 && zahl >= count; count++);
if (count == zahl)
return 1;
return 0;
}
Die Aufgabe besteht darin, zu prüfen, ob eine Zahl eine Primzahl ist oder nicht.
Ich verstehe nicht, warum die for-Schleife hat ; Am Ende:
v
for (count = 2; zahl % count != 0 && zahl >= count; count++);
Ohne das funktioniert der Code nicht richtig.
Was ist die Erklärung?
Die for-Schleife hat am Ende ein Semikolon, weil der Autor EVIL ist! In solchen Situationen sollte es seine eigene Linie gehen.
– sch1
24. April 2015 um 1:29 Uhr
@sh1 Oder, wenn der Autor die gesamte Schleife in einer Zeile haben möchte, { } könnte anstelle von verwendet werden ; um zu dokumentieren, dass es beabsichtigt ist, dass die Schleife einen leeren Körper hat und keine der nachfolgenden Zeilen enthält.
– Eliah Kagan
24. April 2015 um 2:36 Uhr
@EliahKagan, manchmal, wenn ich das Gefühl habe, die Leere des Loop-Körpers betonen zu wollen, schreibe ich for (...) continue;.
– sch1
24. April 2015 um 2:47 Uhr
@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 “geschleift” ist. Letzteres ist eine besondere Gefahr, weil Programmierer lernen, auf das Semikolon am Zeilenende nicht besonders zu achten; Genauso wie Menschen, die lesen, es nicht bemerken, wenn ein Satz nicht mit einem Punkt endet
– Dawud ibn Kareem
24. April 2015 um 12:13 Uhr
@ Marco13 Warum automatisch davon ausgehen, dass der ursprüngliche Autor unwissend ist? Sie hassen diese Art zu schreiben, sehr gut. Aber Sie werden viele Leute finden, die das bevorzugen for Schleifenansatz: Immerhin gibt es eine Initialisierung, eine Stoppbedingung und eine Iteration, was natürlich durch die ausgedrückt wird for konstruieren. Sie sind anderer Meinung, aber ich bin sicher, der Autor weiß, was a while Schleife ist. Übrigens, deshalb brauchen Sie Programmierkonventionen in einem Team.
– Core-Dump
24. April 2015 um 19:43 Uhr
MM
Es bedeutet genau dasselbe wie:
for(count = 2; zahl % count != 0 && zahl >= count; count++)
{
}
Und dies ist eine viel bessere Möglichkeit, einen leeren Schleifenkörper zu schreiben (obwohl das Schreiben {} auf einer einzelnen Linie ist vielleicht ein visuell einfacherer Hinweis auf einen leeren Körper). Wenn es keinen Legacy-Code gäbe, wäre die Sprache ohne die besser dran ; leere Anweisungsregel. Das ; das ist danach Pflicht do ... while(...) ist auch dumm, aber zumindest habe ich dort eine clevere Verwendung davon gesehen.
– Marc van Leeuwen
24. April 2015 um 11:20 Uhr
@MarcvanLeeuwen Ich finde das ; 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 deutlich.
– Paulus
24. April 2015 um 17:32 Uhr
@Paulpro, ich finde beides potenzielle Fehler und for (...) { /* empty block */ } um klarer als beide zu sein, soweit es demonstriert, dass es beabsichtigt ist.
– ank
24. April 2015 um 19:05 Uhr
Ich bin nicht ein C Programmierer, aber warum um alles in der Welt sollte dies jemals nützlich sein?
– Ethan Bierlein
25. April 2015 um 3:43 Uhr
@EthanBierlein die ‘Arbeit’ wird durch die Anweisungen im Inneren erledigt ( ) ; Der Punkt dieser Schleife ist es, mit zu enden count mit einem bestimmten Wert basierend auf zahl
– MM
25. April 2015 um 6:42 Uhr
Elia Kagan
Eine for-Schleife hat die for Schlüsselwort, gefolgt von Klammern, die drei optionale Ausdrücke enthalten, die durch Semikolons getrennt sind, gefolgt von einem Körper, der in jeder Iteration der Schleife ausgeführt wird.
Das Ziel der for-Schleife in Ihrem Beispiel ist es, den Wert von festzulegen countdie verglichen werden zahl in der folgenden if-Anweisung. 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 Rumpf.
Wenn die ; am Ende weggelassen und keine weiteren Änderungen vorgenommen wurden, dann würde die if-Anweisung nach der for-Schleife selbst zum Rumpf der for-Schleife werden. (Das ist nicht beabsichtigt und würde das Programm zerstören, wie Sie bemerkt haben.)
Allerdings besteht der Loop-Körper aus einem Single ; in der gleichen Zeile ist nicht die einzige Möglichkeit, einen leeren Schleifenkörper zu schreiben, und es ist wahrscheinlich auch nicht die vernünftigste Art, dies zu tun. Es funktioniert einwandfrei, aber das Problem ist, dass sich andere Leser – und vielleicht derselbe Programmierer, der später zum Projekt zurückkehrt – fragen könnten, ob es sich tatsächlich um einen Fehler handelt. Schließlich tippt man beim Codieren in einer Sprache im C-Stil ziemlich oft Semikolons am Ende von Zeilen, so dass man leicht ein zusätzliches eintippen kann, wo es nicht hingehört.
Das andere Problem ist, dass im Code eine einzeilige Schleife mit ; Da sein Körper der gewählte Stil ist, ist es schwierig erkenne wenn jemand eigentlich hat den Fehler gemacht, a zu setzen ; wenn man nicht dazugehört.
Daher können diese Alternativen vorzuziehen sein:
setzen die ;eingerückt, in der nächsten Zeile – wie sh1 vorschlägt
Schreiben des Schleifenkörpers als leeren Block, { }anstatt einer leeren Anweisung
Erstellen des Schleifenkörpers a continue; -Anweisung, die einfach bewirkt, dass die Schleife mit ihrer nächsten Iteration fortfährt (was dasselbe ist, was passiert, wenn der Schleifenkörper leer ist) – auch wie sh1 vorschlägt
Wobei ich dem zustimmen kann ; und die {}würde ich finden continue; extrem seltsam. Es würde für mich so aussehen, als ob jemand damit gerechnet hätte continue eine äußere Schleife oder so etwas. Definitiv ein WTF-Moment, und Sie möchten diese im Code vermeiden. ich würde sagen {} erfasst die Absicht auf die lesbarste Weise.
– Angew ist nicht mehr stolz auf SO
24. April 2015 um 9:04 Uhr
Eine weitere Option (die mit den anderen kombiniert werden kann) ist das Einfügen eines Kommentars: for (...) /* do nothing */ ;um deutlich zu machen, dass es beabsichtigt ist.
– Benutzer743382
24. April 2015 um 10:59 Uhr
Ich würde die Alternativen ergänzen Inkrementieren der Variablen innerhalb der Schleifewie: for(count=2; zahl % count != 0 && zahl >= count;) ++count;
– Massa
24. April 2015 um 12:57 Uhr
@Massa – die for Schleife ist per Definition eine gezählte; Das Exportieren des Inkrementors aus der Schleife gibt Ihnen keinen Grund zur Verwendung for vs while was auch immer.
– Benutzer719662
24. April 2015 um 18:06 Uhr
@vaxquis Sie haben immer noch die Initialisierung; Ich wäre mit gegangen int count = 2; while( zahl % count && zahl >= count ) ++count; anfangs trotzdem 😀
– Massa
25. April 2015 um 19:08 Uhr
Rohn Adams
Das Semikolon am Ende der for-Schleife bedeutet, dass sie keinen Körper hat. Ohne dieses Semikolon denkt C die if Die Anweisung ist der Rumpf der for-Schleife.
+int(PI/3) dafür, dass Sie genau richtig sind, ohne in die Debatte „Ist es gut/schlechte Codierungspraxis“ einzusteigen.
– Benutzer719662
24. April 2015 um 18:07 Uhr
Definitiv +1, eine saubere, kurze sachliche Antwort, die nicht versucht, den Code als schlechten oder schlechten Stil zu deklarieren.
– Wertigkeit
24. April 2015 um 21:20 Uhr
Die for-Schleife hat definitiv einen Körper. Es ist nur so, dass der Körper nur aus der Null-Anweisung besteht, ;. Allein ; gilt praktisch (wenn nicht sogar) überall dort, wo eine Aussage erlaubt ist, denn ein Einzelgänger ; ist eine Null-Anweisung (die eine Anweisung ist).
– Benutzer
24. April 2015 um 21:51 Uhr
hackt
Syntax von for Schleife (iterationsanweisung) ist
for ( clause-1 ; expression-2 ; expression-3 ) statement
statement kann ein sein Null-Aussage (;). 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
char *s;
/* ... */
while (*s++ != '\0')
;
eine Null-Anweisung wird verwendet, um der Iterationsanweisung einen leeren Schleifenkörper zuzuführen.
Dasselbe passiert in
for (count = 2; zahl % count != 0 && zahl >= count; count++);
; wird verwendet, um dem einen leeren Schleifenkörper zuzuführen for Aussage. Ohne ; die Aussage neben dem for Schleife wird als sein Körper betrachtet und ausgeführt.
Federico
Zusätzlich zu dem, was die anderen hervorragenden Antworten bereits sagen, möchte ich darauf hinweisen
for(count=2; zahl % count != 0 && zahl >= count; count++);
(das ist ein for Schleife mit einer leeren Anweisung zum Erhöhen eines “Zählers”) ist äquivalent zu
das würde das Ziel des Codes noch klarer machen als einige der aufgelisteten Alternativen: Wenn keine Kommentare vorhanden sind, wie im dargestellten Fall, könnte eine Schleife mit einer leeren Anweisung einen anderen Programmierer verwirren, der den Code (wie er war) pflegen oder verwenden muss der Fall mit dem OP hier).
Der Kontext mag dabei helfen, den wahren Umfang der Aussage zu erkennen, aber zwischen a for Schleife mit einer leeren Anweisung und a while Schleife mit einer Anweisung, letztere erfordert weniger Arbeit, um ihren Umfang zu verstehen.
Minor nitpick: Dies ist seit der zweiten Version nicht unbedingt gleichwertig count wird in einem größeren Umfang deklariert.
– Core-Dump
24. April 2015 um 19:26 Uhr
Ich meine, im Allgemeinen … hier count wird in beiden Versionen am Anfang der Funktion deklariert.
– Core-Dump
24. April 2015 um 19:49 Uhr
@coredump: In Anbetracht dessen, dass der Zweck dieser Schleife – in diesem speziellen Fall – darin besteht, zu erhalten count auf den richtigen Wert, damit es weiter verwendet werden kann, count muss in größerem Umfang existieren, damit das überhaupt funktioniert und ist daher genau gleichwertig. (Es ist immer noch ein hässlicher Missbrauch von a for Schleife, und Federico hat Recht, dass dies der richtige Weg ist, um die beteiligte Semantik auszudrücken.)
– Maurer Wheeler
24. April 2015 um 20:31 Uhr
@MasonWheeler Ja, ich habe über den allgemeinen Fall nachgedacht. Beide sind hier tatsächlich gleichwertig.
– Core-Dump
24. April 2015 um 20:45 Uhr
Warum ist die for-Schleife unklar? Ich habe verstanden, dass eine for-Schleife explizit dazu da war, eine Initialisierung, eine Bedingung und eine iterierende Anweisung logisch zusammenzufassen. Es ist nie notwendig, eine for-Schleife zu verwenden, aber dieser Fall schien vernünftig und sauber geschrieben zu sein.
– Wertigkeit
24. April 2015 um 21:23 Uhr
Das ; nach dem for Schleife bedeutet einfach, dass die for Schleife wird nichts weiter tun, als den Zähler zu erhöhen count.
Minor nitpick: Dies ist seit der zweiten Version nicht unbedingt gleichwertig count wird in einem größeren Umfang deklariert.
– Core-Dump
24. April 2015 um 19:26 Uhr
Ich meine, im Allgemeinen … hier count wird in beiden Versionen am Anfang der Funktion deklariert.
– Core-Dump
24. April 2015 um 19:49 Uhr
@coredump: In Anbetracht dessen, dass der Zweck dieser Schleife – in diesem speziellen Fall – darin besteht, zu erhalten count auf den richtigen Wert, damit es weiter verwendet werden kann, count muss in größerem Umfang existieren, damit das überhaupt funktioniert und ist daher genau gleichwertig. (Es ist immer noch ein hässlicher Missbrauch von a for Schleife, und Federico hat Recht, dass dies der richtige Weg ist, um die beteiligte Semantik auszudrücken.)
– Maurer Wheeler
24. April 2015 um 20:31 Uhr
@MasonWheeler Ja, ich habe über den allgemeinen Fall nachgedacht. Beide sind hier tatsächlich gleichwertig.
– Core-Dump
24. April 2015 um 20:45 Uhr
Warum ist die for-Schleife unklar? Ich habe verstanden, dass eine for-Schleife explizit dazu da war, eine Initialisierung, eine Bedingung und eine iterierende Anweisung logisch zusammenzufassen. Es ist nie notwendig, eine for-Schleife zu verwenden, aber dieser Fall schien vernünftig und sauber geschrieben zu sein.
Die for-Anweisung ist eine Schleifenanweisung, deren Struktur eine einfache Initialisierung von Variablen, Testen von Ausdrücken und Ändern von Variablen ermöglicht. Es ist sehr praktisch, um gegengesteuerte Schleifen zu erstellen. Hier ist die allgemeine Form der for-Anweisung:
Eine Null-Anweisung tut nichts. Es speichert nirgendwo einen Wert. Es führt nicht dazu, dass während der Ausführung Ihres Programms Zeit vergeht.
Meistens 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 Schleifenkörper verwendet (und aus Spaß auch die ganzzahlige Quadratwurzel von n berechnet):
for (i = 1; i*i < n; i++)
;
Hier ist ein weiteres Beispiel, das die Null-Anweisung als Hauptteil einer for-Schleife verwendet und auch eine Ausgabe erzeugt:
for (x = 1; x <= 5; printf ("x is now %d\n", x), x++)
;
Eine Null-Anweisung wird manchmal auch verwendet, um einem Label zu folgen, das sonst das Letzte in einem Block wäre.
Die for-Schleife hat am Ende ein Semikolon, weil der Autor EVIL ist! In solchen Situationen sollte es seine eigene Linie gehen.
– sch1
24. April 2015 um 1:29 Uhr
@sh1 Oder, wenn der Autor die gesamte Schleife in einer Zeile haben möchte,
{ }
könnte anstelle von verwendet werden;
um zu dokumentieren, dass es beabsichtigt ist, dass die Schleife einen leeren Körper hat und keine der nachfolgenden Zeilen enthält.– Eliah Kagan
24. April 2015 um 2:36 Uhr
@EliahKagan, manchmal, wenn ich das Gefühl habe, die Leere des Loop-Körpers betonen zu wollen, schreibe ich
for (...) continue;
.– sch1
24. April 2015 um 2:47 Uhr
@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 “geschleift” ist. Letzteres ist eine besondere Gefahr, weil Programmierer lernen, auf das Semikolon am Zeilenende nicht besonders zu achten; Genauso wie Menschen, die lesen, es nicht bemerken, wenn ein Satz nicht mit einem Punkt endet
– Dawud ibn Kareem
24. April 2015 um 12:13 Uhr
@ Marco13 Warum automatisch davon ausgehen, dass der ursprüngliche Autor unwissend ist? Sie hassen diese Art zu schreiben, sehr gut. Aber Sie werden viele Leute finden, die das bevorzugen
for
Schleifenansatz: Immerhin gibt es eine Initialisierung, eine Stoppbedingung und eine Iteration, was natürlich durch die ausgedrückt wirdfor
konstruieren. Sie sind anderer Meinung, aber ich bin sicher, der Autor weiß, was awhile
Schleife ist. Übrigens, deshalb brauchen Sie Programmierkonventionen in einem Team.– Core-Dump
24. April 2015 um 19:43 Uhr