
Aurón
Mi primer intento de bucle for inverso que hace algo n veces fue algo como:
for ( unsigned int i = n-1; i >= 0; i-- ) {
...
}
Esta falla porque en aritmética sin signo i
se garantiza que siempre es mayor o igual que cero, por lo tanto, la condición del ciclo siempre será verdadera. Afortunadamente, el compilador gcc me advirtió sobre una ‘comparación sin sentido’ antes de que tuviera que preguntarme por qué el bucle se ejecutaba infinitamente.
Estoy buscando una forma elegante de resolver este problema teniendo en cuenta que:
- Debería ser un bucle for al revés.
- El índice de bucle no debe estar firmado.
- n es una constante sin signo.
- No debe basarse en la aritmética de anillos ‘oscura’ de los enteros sin signo.
¿Algunas ideas? Gracias 🙂

esquizo
Qué tal si:
for (unsigned i = n ; i-- > 0 ; )
{
// do stuff with i
}
for ( unsigned int loopIndex = n; loopIndex > 0; --loopIndex ) {
unsigned int i = loopIndex - 1;
...
}
o
for ( unsigned int loopIndex = 0; loopIndex < n; ++loopIndex ) {
unsigned int i = n - loopIndex - 1;
...
}
for ( unsigned int i = n; i != 0; i-- ) {
// do something with i - 1
...
}
Tenga en cuenta que si usa C++ además de C, usar != es un buen hábito para cuando cambie a usar iteradores, donde <= etc. puede no estar disponible.

idz
¿Por qué no simplemente:
unsigned int i = n;
while(i--)
{
// use i
}
Esto cumple con todos los requisitos enumerados en el cuerpo de la pregunta. No utiliza nada que pueda fallar en la revisión del código o violar un estándar de codificación. La única objeción que pude ver es si el OP realmente insistiera en un for
bucle y no una forma sencilla de generar i = (n-1) .. 0.

Pete Kirkham
tendería a usar
for ( unsigned int i = n; i > 0; ) {
--i;
...
}
es casi lo mismo que la respuesta de skizz (se pierde una disminución final innecesaria, pero el compilador debería optimizarla), y en realidad aprobará la revisión del código. Cada estándar de codificación con el que he tenido que trabajar ha tenido una regla condicional de no mutación.

vartec
for ( unsigned int i = n; i > 0; i-- ) {
...
i-1 //wherever you've been using i
}
¿Quizás de esta manera? En mi humilde opinión es claro y legible. Puede omitir if(n>=1) si se conoce implícitamente de alguna manera.
if(n>=1) {
// Start the loop at last index
unsigned int i = n-1;
do {
// a plus: you can use i, not i-1 here
} while( i-- != 0 );
}
Otra version:
if(n>=1) {
unsigned int i = n;
do {
i--;
} while( i != 0 );
}
El primer código sin la instrucción if se vería así:
unsigned int i = n-1;
do {
} while( i-- != 0 );
si n > mayor valor positivo representable por int.
–Pete Kirkham
20 de marzo de 2009 a las 11:38
Luego usa un largo. Y si su matriz es demasiado grande por mucho tiempo, tiene problemas más serios que sin firmar 🙂
– pax diablo
20 de marzo de 2009 a las 11:41
¿Semántica, tal vez? Como nunca debería estar bajo cero.
– Aurón
20 de marzo de 2009 a las 11:42
¿Quién dijo algo sobre una matriz?
– luego
20 de marzo de 2009 a las 11:42
@Pax: por ejemplo, este podría ser un código para un procesador de 16 bits, donde i comienza por encima de 32767. Usar algo más grande que un int sin firmar sería ineficiente.
–Steve Melnikoff
21 de marzo de 2009 a las 17:07