Was Ihr Lehrer gesagt hat, war eine schräge Aussage ohne viel Klarstellung. Es ist NICHT so, dass das Dekrementieren schneller ist als das Inkrementieren, aber Sie können mit dem Dekrementieren eine viel viel schnellere Schleife erstellen als mit dem Inkrementieren.
Ohne ausführlich darauf einzugehen, ohne einen Schleifenzähler usw. verwenden zu müssen - was unten zählt, ist nur die Geschwindigkeit und die Anzahl der Schleifen (nicht Null).
So implementieren die meisten Leute eine Schleife mit 10 Iterationen:
int i;
for (i = 0; i < 10; i++)
{
//something here
}
In 99% der Fälle ist dies alles, was man braucht, aber neben PHP, PYTHON und JavaScript gibt es die ganze Welt zeitkritischer Software (normalerweise eingebettet, Betriebssystem, Spiele usw.), in der CPU-Ticks wirklich wichtig sind. Schauen Sie sich also kurz den Assembler-Code an:
int i;
for (i = 0; i < 10; i++)
{
//something here
}
Nach der Kompilierung (ohne Optimierung) kann die kompilierte Version folgendermaßen aussehen (VS2015):
-------- C7 45 B0 00 00 00 00 mov dword ptr [i],0
-------- EB 09 jmp labelB
labelA 8B 45 B0 mov eax,dword ptr [i]
-------- 83 C0 01 add eax,1
-------- 89 45 B0 mov dword ptr [i],eax
labelB 83 7D B0 0A cmp dword ptr [i],0Ah
-------- 7D 02 jge out1
-------- EB EF jmp labelA
out1:
Die gesamte Schleife besteht aus 8 Befehlen (26 Bytes). Darin - es gibt tatsächlich 6 Anweisungen (17 Bytes) mit 2 Zweigen. Ja, ja, ich weiß, dass es besser geht (es ist nur ein Beispiel).
Betrachten Sie nun dieses häufige Konstrukt, das häufig von eingebetteten Entwicklern geschrieben wird:
i = 10;
do
{
//something here
} while (--i);
Es iteriert auch 10 Mal (ja, ich weiß, dass der Wert anders ist als der für for-Schleife gezeigte, aber wir kümmern uns hier um die Anzahl der Iterationen). Dies kann wie folgt zusammengefasst werden:
00074EBC C7 45 B0 01 00 00 00 mov dword ptr [i],1
00074EC3 8B 45 B0 mov eax,dword ptr [i]
00074EC6 83 E8 01 sub eax,1
00074EC9 89 45 B0 mov dword ptr [i],eax
00074ECC 75 F5 jne main+0C3h (074EC3h)
5 Anweisungen (18 Bytes) und nur ein Zweig. Tatsächlich gibt es 4 Befehle in der Schleife (11 Bytes).
Das Beste ist, dass einige CPUs (einschließlich x86 / x64-kompatibel) Anweisungen haben, die ein Register dekrementieren, das Ergebnis später mit Null vergleichen und eine Verzweigung durchführen können, wenn das Ergebnis von Null abweicht. Praktisch ALLE PC-CPUs implementieren diese Anweisung. Wenn Sie es verwenden, ist die Schleife eigentlich nur eine (ja eine) 2-Byte-Anweisung:
00144ECE B9 0A 00 00 00 mov ecx,0Ah
label:
// something here
00144ED3 E2 FE loop label (0144ED3h) // decrement ecx and jump to label if not zero
Muss ich erklären, was schneller ist?
Selbst wenn eine bestimmte CPU den obigen Befehl nicht implementiert, ist nur ein Dekrement gefolgt von einem bedingten Sprung erforderlich, wenn das Ergebnis des vorherigen Befehls zufällig Null ist.
Unabhängig von einigen Fällen, in denen Sie als Kommentar darauf hinweisen können, warum ich falsch liege usw. usw. Ich betone - JA, es ist von Vorteil, nach unten zu springen, wenn Sie wissen, wie, warum und wann.
PS. Ja, ich weiß, dass der kluge Compiler (mit der entsprechenden Optimierungsstufe) die Schleife (mit aufsteigendem Schleifenzähler) in do umschreibt, während sie für konstante Schleifeniterationen äquivalent ist ... (oder sie entrollt) ...