O que seu professor disse foi uma declaração oblíqua, sem muitos esclarecimentos. NÃO é que o decremento seja mais rápido que o incremento, mas você pode criar um loop muito mais rápido com o decremento do que com o incremento.
Sem falar muito sobre isso, sem a necessidade de usar o contador de loop, etc - o que importa abaixo é apenas a velocidade e a contagem de loop (diferente de zero).
Aqui está como a maioria das pessoas implementa loop com 10 iterações:
int i;
for (i = 0; i < 10; i++)
{
//something here
}
Para 99% dos casos, é tudo o que precisamos, mas junto com PHP, PYTHON, JavaScript, existe todo o mundo de software crítico de tempo (geralmente incorporado, SO, jogos, etc.) em que os tiques de CPU realmente importam, então veja brevemente o código de montagem de:
int i;
for (i = 0; i < 10; i++)
{
//something here
}
após a compilação (sem otimização), a versão compilada pode ser assim (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:
O loop inteiro é de 8 instruções (26 bytes). Nele - na verdade existem 6 instruções (17 bytes) com 2 ramificações. Sim, sim, eu sei que isso pode ser feito melhor (é apenas um exemplo).
Agora considere essa construção frequente que você encontrará com frequência por escrito pelo desenvolvedor incorporado:
i = 10;
do
{
//something here
} while (--i);
Ele também itera 10 vezes (sim, eu sei que o valor é diferente em comparação com o loop for mostrado, mas nos preocupamos com a contagem de iterações aqui). Isso pode ser compilado para isso:
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 instruções (18 bytes) e apenas um ramo. Na verdade, existem 4 instruções no loop (11 bytes).
O melhor é que algumas CPUs (compatíveis com x86 / x64) possuem instruções que podem diminuir um registro, comparar o resultado com zero e executar ramificações se o resultado for diferente de zero. Praticamente todos os cpus de PC implementam esta instrução. Utilizando-o, o loop é na verdade apenas uma (sim uma) instrução de 2 bytes:
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
Eu tenho que explicar o que é mais rápido?
Agora, mesmo que uma CPU específica não implemente a instrução acima, tudo o que é necessário para emular é um decremento seguido de salto condicional se o resultado da instrução anterior for zero.
Portanto, independentemente de alguns casos que você possa apontar como comentário, por que eu estou errado, etc, etc. EU SALIENTO - SIM É BENEFICIAL FAZER LOOP DOWNWARDS se você souber como, por que e quando.
PS. Sim, eu sei que o compilador inteligente (com nível de otimização apropriado) reescreverá o loop (com contador de loop ascendente) em do..time equivalente a iterações constantes do loop ... (ou desenrolá-lo) ...