it-swarm.com.de

Ist "for (;;)" schneller als "while (TRUE)"? Wenn nicht, warum benutzen die Leute es?

for (;;) {
    //Something to be done repeatedly
}

Ich habe gesehen, dass so etwas oft gebraucht wird, aber ich finde es ziemlich seltsam ... Wäre es nicht viel klarer, while(true) zu sagen, oder etwas in diese Richtung?

Ich vermute, dass (wie der Grund für viele Programmierer, auf kryptischen Code zurückzugreifen) dies eine winzige Marge schneller ist?

Warum und ist es wirklich wert? Wenn ja, warum nicht einfach so definieren:

#define while(true) for(;;)

Siehe auch: Was ist schneller: while (1) oder while (2)?

158
Chris Cooper
  1. Schneller geht es nicht.
  2. Wenn es Ihnen wirklich wichtig ist, kompilieren Sie die Assembler-Ausgabe für Ihre Plattform und schauen Sie, ob Sie sie sehen können.
  3. Es spielt keine Rolle. Das ist nie wichtig. Schreiben Sie Ihre Endlosschleifen, wie Sie möchten.
255
Ben Zotto

Ich bevorzuge for(;;) aus zwei Gründen.

Eine davon ist, dass einige Compiler Warnungen für while(true) erzeugen (so etwas wie "Schleifenbedingung ist konstant"). Warnungen zu vermeiden ist immer eine gute Sache.

Eine andere ist, dass ich denke, dass for(;;) klarer und aussagekräftiger ist. Ich möchte eine Endlosschleife. Es ist buchstäblich hat keine Bedingung, es hängt von nichts ab. Ich möchte nur, dass es für immer weitergeht, bis ich etwas unternehme, um daraus auszubrechen.

Wohingegen mit while(true), nun, was hat das mit irgendetwas zu tun? Ich bin nicht daran interessiert, eine Schleife zu machen, bis true zu false wird, was in dieser Form wörtlich gesagt wird (loop while true is true). Ich möchte nur eine Schleife machen.

Und nein, es gibt absolut keinen Leistungsunterschied.

169
jalf

Persönlich benutze ich for (;;), weil keine Zahlen darin sind, es ist nur ein Schlüsselwort. Ich bevorzuge es zu while (true), while (1), while (42), while (!0) etc etc.

56
ta.speot.is

Wegen Dennis Ritchie

  • Ich habe angefangen, for (;;) zu verwenden, weil Dennis Ritchie es in K & R so macht, und wenn ich eine neue Sprache lerne, versuche ich immer, die Schlauen zu imitieren.

  • Das ist idiomatisch C/C++. Es ist wahrscheinlich auf lange Sicht besser, sich daran zu gewöhnen, wenn Sie vorhaben, viel im C/C++ - Bereich zu tun.

  • Ihre #define funktioniert nicht, da das zu definierende Objekt wie ein C-Bezeichner aussehen muss.

  • Alle modernen Compiler generieren denselben Code für die beiden Konstrukte.

49
Mark Harrison

Schneller geht es in keinem vernünftigen Compiler. Sie werden beide zu bedingungslosen Sprüngen zusammengefasst. Die for-Version ist einfacher zu tippen (wie Neil sagte) und wird klar sein, wenn Sie die Schleifensyntax verstehen.

Wenn Sie neugierig sind, ist hier, was gcc 4.4.1 mir für x86 gibt. Beide verwenden die Anweisung x86 JMP .

void while_infinite()
{
    while(1)
    {
    puts("while");
    }
}

void for_infinite()
{
    for(;;)
    {
    puts("for");
    }
}

kompiliert zu (teilweise):

.LC0:
.string "while"
.text
.globl while_infinite
    .type   while_infinite, @function
while_infinite:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $24, %esp
.L2:
    movl    $.LC0, (%esp)
    call    puts
    jmp .L2
    .size   while_infinite, .-while_infinite
    .section    .rodata
.LC1:
    .string "for"
    .text
.globl for_infinite
    .type   for_infinite, @function
for_infinite:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $24, %esp
.L5:
    movl    $.LC1, (%esp)
    call    puts
    jmp .L5
    .size   for_infinite, .-for_infinite
46

Ich bevorzuge for (;;), weil es in verschiedenen C-ähnlichen Sprachen am konsistentesten ist.

In C++ ist while (true) in Ordnung, aber in C sind Sie auf einen Header angewiesen, um true zu definieren, doch TRUE ist auch ein häufig verwendetes Makro. Wenn Sie while (1) verwenden, ist dies in C und C++ sowie in JavaScript korrekt, jedoch nicht in Java oder C #), für das die Schleifenbedingung ein Boolescher Wert sein muss, z. B. while (true) oder while (1 == 1). In PHP wird bei Schlüsselwörtern die Groß- und Kleinschreibung nicht beachtet, aber die Sprache bevorzugt die Groß- und Kleinschreibung TRUE.

Allerdings ist for (;;) in all diesen Sprachen immer vollständig korrekt.

41
Boann

Ich persönlich bevorzuge das for (;;)-Idiom (das mit demselben Code kompiliert wird wie while (TRUE).

Die Verwendung von while (TRUE) kann in gewisser Hinsicht besser lesbar sein. Ich habe mich für die Verwendung der for (;;) - Redewendung entschieden, weil sie steht hervor.

Ein Endlosschleifenkonstrukt sollte im Code leicht zu bemerken oder aufzurufen sein, und ich persönlich denke, dass der for (;;) -Stil dies ein bisschen besser macht als while (TRUE) oder while (1).

Ich erinnere mich auch, dass einige Compiler Warnungen ausgeben, wenn der steuernde Ausdruck einer while-Schleife eine Konstante ist. Ich glaube nicht, dass das zu viel passiert, aber nur das Potenzial für falsche Warnungen reicht aus, um es zu vermeiden.

21
Michael Burr

Ich habe gesehen, dass einige Leute es vorziehen, weil sie irgendwo ein #define haben:

#define EVER ;;

Was ihnen erlaubt, dies zu schreiben:

for (EVER)
{
    /* blah */
}
17
rmeador

Was ist mit (wenn Ihre Sprache dies unterstützt):

start:
/* BLAH */
goto start;
16
bungle

Es gibt keinen Unterschied in Bezug auf den generierten Maschinencode.

Um dem Trend entgegenzuwirken, würde ich jedoch argumentieren, dass das while-Formular (TRUE) viel besser lesbar und intuitiver ist als das for-Formular (;;) und dass Lesbarkeit und Klarheit wesentlich wichtigere Gründe für die Kodierung von Richtlinien sind als alle anderen von mir genannten. Ich habe für den for (;;) -Ansatz gehört (ich ziehe es vor, meine Kodierungsrichtlinien auf solide Argumentation und/oder Wirksamkeitsnachweise zu stützen).

12
Jason Williams

Nicht nur ein bekanntes Muster, sondern eine Standardsprache in C (und C++)

11
James McLeod

Beide sollten gleich sein, wenn Ihr Code vom Compiler optimiert wird. Um zu erklären, was ich unter Optimierung verstehe, ist hier ein in MSVC 10 geschriebener Beispielcode:

int x = 0;

while(true) // for(;;)
{
    x +=1;

    printf("%d", x);
}

Wenn Sie es im Debug-Modus erstellen (ohne Optimierung (/ Od)), zeigt die Demontage den deutlichen Unterschied. Es gibt zusätzliche Anweisungen für die true -Bedingung in while.

while(true)
00D313A5  mov         eax,1                //extra 
00D313AA  test        eax,eax              //extra
00D313AC  je          main+39h (0D313B9h)  //extra
    {
        x +=1;
00D313AE  mov         eax,dword ptr [x]  
00D313B1  add         eax,1  
00D313B4  mov         dword ptr [x],eax  
    printf("%d", x);
    ...
    }
00D313B7  jmp         main+25h (0D313A5h)  


for(;;)
    {
        x +=1;
00D213A5  mov         eax,dword ptr [x]  
00D213A8  add         eax,1  
00D213AB  mov         dword ptr [x],eax  
    printf("%d", x);
    ...
    }
00D213AE  jmp         main+25h (0D213A5h)  

Wenn Sie Ihren Code jedoch im Release-Modus erstellen (standardmäßig Maximize Speed ​​(/ O2)), erhalten Sie für beide dieselbe Ausgabe. Beide Schleifen werden auf einen Sprungbefehl reduziert.

for(;;)
    {
        x +=1;
01291010  inc         esi  

        printf("%d", x);
    ...
    }
0129101C  jmp         main+10h (1291010h)  

    while(true)
    {
        x +=1;
00311010  inc         esi  

        printf("%d", x);
    ...
    }
0031101C  jmp         main+10h (311010h)  

Was auch immer Sie verwenden, spielt für einen anständigen Compiler mit Geschwindigkeitsoptimierung keine Rolle.

11
SylvanBlack
while(true)

generiert eine Warnung mit Visual Studio (Bedingung ist konstant). Die meisten Orte, an denen ich gearbeitet habe, kompilieren Produktionsbuilds mit Warnungen als Fehlern. So

for(;;)

ist bevorzugt.

11
Michael

Es ist eine Frage der persönlichen Präferenz, welcher Weg schneller ist. Persönlich bin ich ein Touchtypist und schaue während des Programmierens nie auf meine Tastatur - ich kann alle 104 Tasten auf meiner Tastatur tippen.

Ich finde, wenn schneller "while (TRUE)" eingeben.

Ich habe in Gedanken einige Fingerbewegungsmessungen hinzugefügt und sie summiert. "for (;;)" hat ungefähr 12 Tastenbreiten für das Zurück und das Vierte (zwischen den Home-Tasten und den Tasten sowie zwischen den Home-Tasten und der UMSCHALTTASTE). "while (TRUE)" hat ungefähr 14 Tastenbreiten für das Zurück und das Zurück vierte.

Ich bin jedoch wesentlich weniger fehleranfällig, wenn ich Letzteres schreibe. Ich denke geistig in Worten nach und finde es daher schneller, Dinge wie "nIndex" als Akronyme wie "nIdx" einzugeben, weil ich den Schriftzug eigentlich geistig buchstabieren muss, anstatt ihn in meinem Kopf auszusprechen und meine Finger automatisch laufen zu lassen -Tippen Sie das Wort (wie Fahrrad fahren)

(Mein TypingTest.com-Benchmark = 136 WPM)

9
Mark Rejhon

Alle guten Antworten - Verhalten sollte genau gleich sein.

JEDOCH - Nimm einfach an, dass es DID einen Unterschied macht. Angenommen, einer von ihnen hat 3 weitere Anweisungen pro Iteration ausgeführt.

Sollte es dich interessieren?

NUR wenn das, was Sie in der Schleife tun, fast nichts ist, was fast nie der Fall ist.

Mein Punkt ist, es gibt Mikrooptimierung und Makrooptimierung. Mikrooptimierung ist wie "einen Haarschnitt bekommen, um Gewicht zu verlieren".

6
Mike Dunlavey

Ich kann mir nicht vorstellen, dass ein lohnender Compiler irgendeinen anderen Code erzeugen würde. Selbst wenn dies der Fall wäre, gäbe es keine Möglichkeit zu bestimmen, ohne den speziellen Compiler zu testen, der effizienter ist.

Ich schlage jedoch vor, dass Sie for(;;) aus den folgenden Gründen bevorzugen:

  • eine Reihe von Compilern, die ich verwendet habe, generiert eine konstante Ausdruckswarnung für while (true) mit entsprechenden Einstellungen für die Warnstufe.

  • in Ihrem Beispiel ist das Makro TRUE möglicherweise nicht wie erwartet definiert

  • es gibt viele mögliche Varianten der unendlichen while-Schleife wie while(1), while(true), while(1==1) etc .; Daher führt for(;;) wahrscheinlich zu einer größeren Konsistenz.

5
Clifford
for(;;Sleep(50))
{
    // Lots of code
}

Ist ein klarer als:

while(true)
{
    // Lots of code
    Sleep(50);
}

Dies gilt jedoch nicht, wenn Sie Sleep() nicht verwenden.

5
Armada

Die "forever" -Schleife ist in eingebetteten Systemen als Hintergrundschleife beliebt. Einige Leute implementieren es als:

for (; ;)
{
 // Stuff done in background loop
}

Und manchmal wird es implementiert als:

while (TRUE /* or use 1 */)
{
 // Stuff done in background loop
}

Und noch eine andere Implementierung ist:

do
{
 // Stuff done in background loop
} while (1 /* or TRUE */);

Ein optimierender Compiler sollte für diese Fragmente den gleichen oder einen ähnlichen Assembly-Code generieren. Ein wichtiger Hinweis: Die Ausführungszeit für die Schleifen ist kein großes Problem, da diese Schleifen für immer andauern und mehr Zeit im Verarbeitungsabschnitt verbracht wird.

4
Thomas Matthews

Ich nehme an, während (true) lesbarer ist als für (;;) - es sieht so aus, als würde der Programmierer etwas in der for-Schleife vermissen :)

und wen interessiert es, welcher schneller ist, wenn überhaupt

2
nik

Der wichtigste Grund für die Verwendung von "for (;;)" ist die Angst davor, "while (TRUE)" zu verwenden, wenn Sie eine explorative Programmierung durchführen. Es ist einfacher, die Anzahl der Wiederholungen mit "for" zu steuern und die "for" -Schleife in eine unendliche zu konvertieren.

Wenn Sie beispielsweise eine rekursive Funktion erstellen, können Sie die Anzahl der Aufrufe der Funktion begrenzen, bevor Sie sie in eine Endlosschleife konvertieren.

    for(int i=0;i<1000;i++) recursiveFunction(oneParam);

Wenn ich mir meiner Funktion sicher bin, konvertiere ich sie in eine Endlosschleife:

    for(;;) recursiveFunction(oneParam);
2