To, co powiedział twój nauczyciel, było jakimś ukośnym stwierdzeniem, bez większego wyjaśnienia. To NIE jest tak, że dekrementacja jest szybsza niż inkrementacja, ale możesz stworzyć dużo szybszą pętlę z dekrementacją niż z przyrostem.
Nie wdając się w to zbyt długo, bez potrzeby używania licznika pętli itp. - poniżej liczy się tylko prędkość i liczba pętli (niezerowa).
Oto jak większość ludzi implementuje pętlę z 10 iteracjami:
int i;
for (i = 0; i < 10; i++)
{
}
W 99% przypadków jest to wszystko, czego możesz potrzebować, ale wraz z PHP, PYTHON, JavaScript istnieje cały świat oprogramowania krytycznego czasowo (zwykle wbudowane, system operacyjny, gry itp.), W których znaczniki procesora naprawdę mają znaczenie, więc spójrz krótko na kod asemblera:
int i;
for (i = 0; i < 10; i++)
{
}
po kompilacji (bez optymalizacji) wersja skompilowana może wyglądać następująco (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:
Cała pętla to 8 instrukcji (26 bajtów). W nim - faktycznie jest 6 instrukcji (17 bajtów) z 2 gałęziami. Tak tak, wiem, że można to zrobić lepiej (to tylko przykład).
Rozważmy teraz tę częstą konstrukcję, którą często można znaleźć napisaną przez programistę embedded:
i = 10;
do
{
} while (--i);
Iteruje również 10 razy (tak, wiem, że wartość i jest inna niż pokazana pętla for, ale tutaj zależy nam na liczbie iteracji). Można to skompilować w następujący sposób:
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 instrukcji (18 bajtów) i tylko jedna gałąź. Właściwie w pętli są 4 instrukcje (11 bajtów).
Najlepsze jest to, że niektóre procesory (w tym kompatybilne z x86 / x64) mają instrukcję, która może zmniejszyć rejestr, później porównać wynik z zerem i wykonać rozgałęzienie, jeśli wynik jest różny od zera. Praktycznie WSZYSTKIE procesory PC realizują tę instrukcję. Używając go, pętla jest w rzeczywistości tylko jedną (tak) 2-bajtową instrukcją:
00144ECE B9 0A 00 00 00 mov ecx,0Ah
label:
00144ED3 E2 FE loop label (0144ED3h)
Czy muszę wyjaśniać, co jest szybsze?
Teraz, nawet jeśli dany procesor nie implementuje powyższej instrukcji, wszystko, czego wymaga do emulacji, jest to dekrementacja, po której następuje skok warunkowy, jeśli wynik poprzedniej instrukcji wynosi zero.
Więc niezależnie od niektórych przypadków, które możesz wskazać w komentarzu, dlaczego się mylę itp. PODKREŚLAJ - TAK, KORZYSTNE JEST PĘTLA W DÓŁ, jeśli wiesz jak, dlaczego i kiedy.
PS. Tak, wiem, że mądry kompilator (z odpowiednim poziomem optymalizacji) przepisze pętlę for (z licznikiem pętli rosnącej) na do.., podczas gdy odpowiednik dla iteracji w pętli stałej ...