Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Regla 0x1009h: Prohibición de asignaciones simples dentro de condiciones lógicas

Estructuras de control y flujo (0x10XX)

Universidad Nacional de Río Negro

0x1009h: Prohibición de asignaciones simples dentro de condiciones lógicas

Enunciado normativo

NO DEBE usarse el operador de asignación = dentro de la condición de un if, while, for o de cualquier otra estructura de control. La asignación DEBE realizarse en una sentencia previa y la condición DEBE limitarse a comparar.

¿Por qué existe esta regla?

El problema

= y == se parecen lo suficiente como para que un dedo cambie uno por otro. El compilador no siempre avisa: if (x = 5) es válido y asigna 5, condición siempre verdadera. El programa compila, arranca y produce un resultado incorrecto que parece inexplicable.

Aun cuando la asignación sea intencional, mezclar “guardar” y “preguntar” en la misma sentencia viola el principio de una acción por sentencia. El lector no puede saber de un vistazo si hubo intención o error.

Consecuencias de violarla

Tipo de consecuenciaEfecto concreto
Bug silenciosoif (estado = ACTIVO) deja estado en ACTIVO y siempre entra.
Pérdida de datosLa variable se sobrescribe con el valor de la comparación.
LegibilidadNo se distingue la intención de asignar de la de comparar.
DepuraciónEl cambio de estado ocurre en una línea que no parece asignar.

Fundamento en el estándar y en la cátedra

ISO/IEC 9899:2011 §6.5.16 define la asignación como expresión que devuelve el valor asignado; por eso es sintácticamente legal dentro de una condición. La cátedra la prohíbe por su historial como causa de bugs. 0x1012h: Prohibición de expresiones de asignación dentro de estructuras de control extiende la prohibición a las asignaciones embebidas con comparación, como while ((c = getchar()) != EOF).

Alcance y excepciones

Ejemplos exhaustivos

❌ Contraejemplo 1 — = accidental por ==

if (estado = ACTIVO)
{
    reactivar();
}

Por qué falla: asigna ACTIVO a estado y entra siempre que ACTIVO sea distinto de cero. El estado real del sistema se pierde en la comparación.

❌ Contraejemplo 2 — asignación oculta en un while

int total = 0;
while (valor = siguiente())
{
    total += valor;
}

Por qué falla: valor se pisa en cada iteración y la condición es verdadera mientras el valor leído no sea cero. Si la intención era comparar, el lazo no termina cuando debería.

✅ Ejemplo conforme 1 — asignación separada de la comparación

estado = obtener_estado();
if (estado == ACTIVO)
{
    reactivar();
}

La asignación es una acción visible y la condición solo pregunta. El error de tipeo queda imposible.

✅ Ejemplo conforme 2 — lectura separada en el lazo

int valor = siguiente();
int total = 0;
while (valor != 0)
{
    total += valor;
    valor = siguiente();
}

El avance es explícito y la condición compara contra 0; se lee sin ambigüedad qué detiene el lazo.

⚠️ Casos límite

Cómo detectarla

HerramientaComandoSeñal
gaffgaff check archivo.cRegla 0x1009h: asignación en condición.
gccgcc -Wall -Wextra -Wparentheseswarning: suggest parentheses around assignment used as truth value.
Búsquedagrep -nE "if \([^=]*[^=!<>]=[^=]" archivo.cPosibles asignaciones en condiciones.

Checklist de autocontrol

Reglas relacionadas

Antipatrón: Asignación accidental en condición lógica (if (x = 5))

Síntoma en el código del estudiante

La condición de un if o while usa = en lugar de ==, y la variable aparenta compararse pero en realidad se sobrescribe:

if (x = 5)
{
    procesar();
}

Diagnóstico

Mecanismo del defecto

En C la asignación es una expresión que devuelve el valor asignado (ISO/IEC 9899:2011 §6.5.16). El if evalúa ese valor: x = 5 asigna 5 y la condición resulta verdadera. La variable queda modificada de forma lateral, sin que ninguna línea lo anuncie.

Consecuencia observable

El if siempre entra (si el valor asignado no es cero) y x cambia de valor. En un while, el lazo puede no terminar nunca o terminar antes de tiempo. El compilador no distingue la intención: compila sin error y, a lo sumo, avisa de la asignación usada como valor de verdad si se activa -Wparentheses.

Fundamento en el estándar C11

ISO/IEC 9899:2011 §6.5.16 define la asignación como expresión con valor, y §6.8.4.1 permite cualquier expresión escalar como condición. El estándar no prohíbe el patrón; la cátedra sí, porque su historial como causa de bugs es extenso. La prohibición es de la regla 0x1009h.

Corrección idiomática

❌ Código con el antipatrón
if (x = 5)
{
    procesar();
}

while (valor = siguiente())
{
    acumular(valor);
}
✅ Código refactorizado
if (x == 5)
{
    procesar();
}

valor = siguiente();
while (valor != 0)
{
    acumular(valor);
    valor = siguiente();
}

La comparación usa == y la asignación se separa de la condición. El while expone su corte comparando contra 0 y el avance es explícito.

Errores típicos al compilar o ejecutar

Con -Wparentheses (incluida en -Wall):
warning: suggest parentheses around assignment used as truth value
[-Wparentheses]

Sin advertencias: el programa compila y entra siempre a la rama,
o el while nunca termina si el valor asignado nunca llega a cero.

Checklist de verificación

Reglas relacionadas