El tipo de condicional utilizado en un bucle puede limitar los tipos de optimizaciones que puede realizar un compilador, para bien o para mal. Por ejemplo, dado:
uint16_t n = ...;
for (uint16_t i=1; i<=n; i++)
... [loop doesn't modify i]
un compilador podría suponer que la condición anterior debería hacer que el ciclo salga después del enésimo paso a menos que n pueda ser 65535 y el ciclo pueda salir de alguna otra manera que no sea excediendo n. Si se aplican esas condiciones, el compilador debe generar un código que haga que el ciclo se ejecute hasta que algo más que la condición anterior lo haga salir.
Si el bucle se hubiera escrito como:
uint16_t n = ...;
for (uint16_t ctr=0; ctr<n; ctr++)
{
uint16_t i = ctr+1;
... [loop doesn't modify ctr]
}
entonces un compilador podría asumir con seguridad que el ciclo nunca necesitaría ejecutarse más de n veces y, por lo tanto, podría generar un código más eficiente.
Tenga en cuenta que cualquier desbordamiento con tipos firmados puede tener consecuencias desagradables. Dado:
int total=0;
int start,lim,mult; // Initialize values somehow...
for (int i=start; i<=lim; i++)
total+=i*mult;
Un compilador podría reescribir eso como:
int total=0;
int start,lim,mult; // Initialize values somehow...
int loop_top = lim*mult;
for (int i=start; i<=loop_top; i+=mult)
total+=i;
Tal bucle se comportaría de manera idéntica al original si no se produce un desbordamiento en los cálculos, pero podría ejecutarse para siempre, incluso en plataformas de hardware donde el desbordamiento de enteros normalmente tendría una semántica de ajuste consistente.