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

Lesezeit: 11 Minuten

Benutzeravatar von Wien95
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


Benutzeravatar von MM
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

Benutzeravatar von Eliah Kagan
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

Benutzeravatar von Rohn Adams
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


Benutzeravatar von hackks
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.

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

count=2;
while(zahl % count != 0  && zahl >= count)
{
    count++;
}

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.

    – Wertigkeit

    24. April 2015 um 21:23 Uhr


for Aussage:

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:

 for (initialize; test; step)
   statement

[…]

Null-Anweisung:

Das Null-Aussage ist nur ein Semikolon allein.

 ;

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.


In Ihrem Fall die ; ist der Null-Anweisung des for Aussage:

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

Ohne sie ist die if wird zur for-Anweisung:

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

Daher anders verhalten.

  • Schön aus der Dokumentation zitiert. +1

    – Wertigkeit

    24. April 2015 um 21:24 Uhr

1417680cookie-checkWas ist der Zweck von “;” am Ende der for-Schleife?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy