Regla 0x1003h: Utilizá el lazo for para iteraciones con rango o contador definido y while para lazos controlados por condiciones lógicas
Estructuras de control y flujo (0x10XX)
0x1003h: Utilizá el lazo for para iteraciones con rango o contador definido y while para lazos controlados por condiciones lógicas¶
Enunciado normativo¶
DEBE usarse el lazo
forcuando la cantidad de iteraciones sea conocida de antemano o esté gobernada por un contador o rango. DEBE reservarse el lazowhilepara iteraciones cuya condición sea puramente lógica o se conozca recién en tiempo de ejecución.
¿Por qué existe esta regla?¶
El problema¶
Cada lazo comunica una intención. El for dice “recorro un rango conocido” y
reúne inicialización, cota e incremento en una sola línea; el lector ve todo el
contrato de una vez. El while dice “repito mientras se cumpla una condición”
y separa el avance del encabezado, porque el avance puede depender del cuerpo.
Usar el lazo equivocado esconde esa intención. Un for con condición compuesta
o con cláusulas vacías es un while disfrazado; un while que cuenta
iteraciones obliga a buscar el incremento dentro del cuerpo y es la causa
habitual del lazo infinito por olvido.
Consecuencias de violarla¶
| Tipo de consecuencia | Efecto concreto |
|---|---|
| Lazo infinito | while de conteo al que se le olvida el incremento. |
| Legibilidad | No se distingue a simple vista si el lazo recorre un rango o espera un evento. |
| Mantenibilidad | Cambiar la cota obliga a ubicar y tocar el cuerpo, no el encabezado. |
| Bug lógico | Un for con condición compuesta oculta varias condiciones de corte. |
Fundamento en el estándar y en la cátedra¶
ISO/IEC 9899:2011 §6.8.5.3 describe el for como azúcar sintáctico de un
while; son equivalentes en poder expresivo. La cátedra elige uno u otro por
su valor comunicativo: for para conteos acotados, while para condiciones.
Se alinea con 0x100Dh: Prohibición de condiciones de parada compuestas complejas en lazos for, que prohíbe cotas compuestas en el for.
Alcance y excepciones¶
for: rangos, arreglos, conteos con incremento regular.while: lectura hasta centinela, validación de entrada, espera de evento.do-while: cuando el cuerpo debe ejecutarse al menos una vez, por ejemplo pedir datos hasta que sean válidos.No hay una forma “más rápida”: ambos compilan a lo mismo.
Ejemplos exhaustivos¶
❌ Contraejemplo 1 — for para una condición lógica¶
for (int n = leer(); n != 0; n = leer())
{
procesar(n);
}Por qué falla: no hay contador ni rango; la cantidad de iteraciones se decide
por el valor leído. El for fuerza a duplicar la lectura en la inicialización y
en el incremento, y si el paso cambia hay que tocar dos lugares.
❌ Contraejemplo 2 — while usado para contar¶
int i = 0;
while (i < cantidad)
{
total += valores[i];
}Por qué falla: falta i++. El lazo nunca termina y accede siempre a
valores[0]. El for habría impedido esa omisión porque el incremento es
obligatorio en la sintaxis.
✅ Ejemplo conforme 1 — for para recorrer un rango¶
for (size_t i = 0; i < cantidad; i++)
{
total += valores[i];
}Inicialización, cota e incremento viven juntos; el recorrido se lee completo en el encabezado y no hay forma de olvidar el avance.
✅ Ejemplo conforme 2 — while para leer hasta centinela¶
int n = leer();
while (n != 0)
{
procesar(n);
n = leer();
}La condición depende del dato leído, no de un contador; el while es la
elección idiomática. El avance está en el cuerpo porque la lectura es la
operación que define el corte.
⚠️ Casos límite¶
Rango
[a, b)vs[a, b]: conforla cota semiabiertai < bes la forma segura frente al off-by-one (ver 0x100Dh: Prohibición de condiciones de parada compuestas complejas en lazos for).Lazo que se ejecuta al menos una vez: el
do-whilees el único que lo garantiza; no forzarlo conwhiley una lectura previa duplicada.forsin uso del índice: si el contador no se usa, probablemente el lazo debería ser unwhilecon condición lógica.
Cómo detectarla¶
| Herramienta | Comando | Señal |
|---|---|---|
gaff | gaff check archivo.c | Regla 0x1003h: elección de lazo. |
| Revisión manual | — | for con condición compuesta o while sin avance. |
gcc | gcc -Wall -Wextra -O2 | warning de variable puede quedar sin cambiar. |
Checklist de autocontrol¶
¿Puedo decir en una frase si el lazo recorre un rango o espera un evento?
Si es un rango, ¿usé
forcon el incremento en el encabezado?Si es una condición lógica, ¿usé
whiley el avance está en el cuerpo?¿Necesito que el cuerpo se ejecute al menos una vez? Entonces
do-while.
Reglas relacionadas¶
0x100Dh: Prohibición de condiciones de parada compuestas complejas en lazos for — la cota del
fordebe ser simple; si no, pasá awhile.0x1002h: Restringí el uso de break y continue; preferí lazos con bandera de control — elegir el lazo correcto reduce la necesidad de
break.0x100Eh: Delimitación obligatoria con bloque de llaves en lazos do-while — el
do-whileexige llaves en su cuerpo.
Antipatrón: Modificación de variable de control dentro del cuerpo del for¶
Síntoma en el código del estudiante¶
El cuerpo del for altera la variable de control, que ya se modifica en el
incremento del encabezado:
for (int i = 0; i < n; i++)
{
if (condicion)
{
i += 2;
}
}Diagnóstico¶
Mecanismo del defecto¶
El for reserva la modificación del contador para su cláusula de incremento.
Cuando el cuerpo también la modifica, hay dos dueños del avance: el lector no
puede calcular cuántas iteraciones habrá mirando el encabezado, y una misma
ejecución puede saltar pasos o retroceder sin que se vea.
Consecuencia observable¶
El número de iteraciones deja de estar determinado por i < n. Aparecen
comportamientos tipo “recorrió la mitad” o “se pasó del límite”, y el acceso a
valores[i] puede salirse del arreglo. El lazo se vuelve difícil de razonar y
de probar.
Fundamento en el estándar C11¶
ISO/IEC 9899:2011 §6.8.5.3 permite modificar cualquier variable dentro del
cuerpo, incluida la de control; la restricción es de diseño. La cátedra exige
que el avance regular quede en el encabezado. Cuando el avance depende de
condiciones dinámicas, la estructura adecuada es el while, donde el contador
es parte de la lógica (regla 0x1003h).
Corrección idiomática¶
❌ Código con el antipatrón¶
for (int i = 0; i < n; i++)
{
if (condicion)
{
i += 2;
}
procesar(valores[i]);
}✅ Código refactorizado¶
int i = 0;
while (i < n)
{
if (condicion)
{
i += 2;
}
else
{
i++;
}
procesar(valores[i]);
}El while deja el avance en el cuerpo, que es donde realmente se decide. Ahora
el lector sigue todos los cambios del contador en un mismo lugar.
Errores típicos al compilar o ejecutar¶
No hay error de compilación. El lazo puede:
- saltear elementos sin procesar,
- saltar el último índice,
- acceder a valores[i] con i >= n si el salto cruza la cota.
Con -fsanitize=address puede reportar stack-buffer-overflow en el acceso.Checklist de verificación¶
¿El cuerpo del
formodifica la variable de control?¿El avance es regular o depende de una condición?
Si es irregular, ¿cambié la estructura a
while?¿Puedo predecir las iteraciones mirando solo el encabezado?
Reglas relacionadas¶
0x1003h: Utilizá el lazo for para iteraciones con rango o contador definido y while para lazos controlados por condiciones lógicas — norma este antipatrón: elección del lazo según el control.
0x100Dh: Prohibición de condiciones de parada compuestas complejas en lazos for — la condición del
fordebe ser una cota simple.0x300Ch: Verificá siempre los límites de los arreglos antes de acceder a sus elementos — verificar límites antes de acceder al arreglo.