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 0x1001h: Todas las estructuras de control deben utilizar llaves

Estructuras de control y flujo (0x10XX)

Universidad Nacional de Río Negro

0x1001h: Todas las estructuras de control deben utilizar llaves

Enunciado normativo

DEBE delimitarse con llaves { } el cuerpo de toda estructura de control (if, else, for, while, do-while y switch), aunque contenga una única sentencia.

Escribir el cuerpo sin llaves, aunque sea sintácticamente válido, queda prohibido en todas las entregas de la cátedra.

¿Por qué existe esta regla?

El problema

En C una estructura de control gobierna exactamente una sentencia, que puede ser un bloque { ... } o una sentencia suelta. Cuando se omite la llave, agregar después una segunda instrucción “dentro” del if es un cambio que el compilador acepta en silencio: la instrucción nueva queda fuera del control. El error no se manifiesta al escribir, sino al leer y al mantener.

La llave convierte la intención en sintaxis. Con llaves, el cuerpo es un bloque explícito y cualquier sentencia agregada entre ellas pertenece al control por construcción, no por posición.

Consecuencias de violarla

Tipo de consecuenciaEfecto concreto
Bug lógicoUna sentencia nueva se agrega fuera del if/for y se ejecuta siempre.
Ambigüedad sintácticaEn if anidados, el else se asocia al if más próximo, no al que se pretendía.
Sentencia nulaUn ; accidental tras la condición desacopla el bloque del control.
MantenibilidadEl diff de una corrección futura puede invertir el sentido del código sin aviso.

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

El estándar ISO/IEC 9899:2011 §6.8.4 define que el cuerpo de un if es una statement, que puede ser compuesta (bloque) o simple. La cátedra adopta la forma compuesta obligatoria como defensa barata contra los defectos anteriores; complementa a 0x0007h: Las llaves deben ubicarse en líneas independientes según el estilo Allman, que fija el estilo de llaves Allman.

Alcance y excepciones

Aplica a toda estructura de control en código de estudiante, sin importar la cantidad de sentencias del cuerpo. No hay excepción por “una sola línea”. Los cuerpos vacíos intencionales (if (x); o while (getchar() != '\n');) siguen prohibidos por 0x100Ah: Prohibición de estructuras de control con cuerpo vacío (if (...);); si el cuerpo está vacío, la llave no lo salva.

Ejemplos exhaustivos

❌ Contraejemplo 1 — if sin llaves con sentencia agregada después

if (temperatura > 100)
    apagar_horno();
    registrar_evento("apagado");

Por qué falla: registrar_evento no está dentro del if; se ejecuta siempre, incluso con el horno frío. La indentación engaña, la semántica no.

❌ Contraejemplo 2 — else colgado en anidamiento sin llaves

if (usuario_valido)
    if (clave_correcta)
        permitir_acceso();
else
    denegar_acceso();

Por qué falla: el else pertenece al if (clave_correcta), no al if (usuario_valido). Un usuario inválido nunca ejecuta denegar_acceso().

✅ Ejemplo conforme 1 — llaves en cada nivel

if (usuario_valido)
{
    if (clave_correcta)
    {
        permitir_acceso();
    }
    else
    {
        denegar_acceso();
    }
}

El bloque exterior deja explícito a qué if pertenece cada else, y agregar sentencias dentro de cualquier rama no cambia el control.

✅ Ejemplo conforme 2 — llaves con una sola sentencia

for (size_t i = 0; i < cantidad; i++)
{
    total += valores[i];
}

Aunque el cuerpo tenga una única línea, la llave documenta el alcance y evita que un if de depuración agregado mañana quede fuera del lazo.

⚠️ Casos límite

Cómo detectarla

HerramientaComandoSeñal
gaffgaff check archivo.cRegla 0x1001h: cuerpo sin llaves.
gccgcc -Wall -Wextra -Wmisleading-indentation -Wdangling-elsewarning: this 'else' clause does not guard...
Revisión visualCondición seguida de sentencia indentada sin {.

Checklist de autocontrol

Reglas relacionadas

Antipatrón: Punto y coma accidental tras condición de control

Síntoma en el código del estudiante

Después de la condición de un if, while o for aparece un ; pegado al paréntesis, y a continuación un bloque entre llaves que se pretende parte del control:

if (x > 0);
{
    hacer_algo();
}

La indentación sugiere que el bloque pertenece al if, pero el ; ya cerró el cuerpo con una sentencia vacía.

Diagnóstico

Mecanismo del defecto

En C, el ; es una sentencia nula válida (ISO/IEC 9899:2011 §6.8.3). El compilador la toma como el cuerpo del if: la condición se evalúa y, si es verdadera, ejecuta “nada”. El bloque siguiente es una sentencia compuesta independiente que se ejecuta siempre, haya o no cumplido la condición.

Consecuencia observable

El programa compila sin errores y el bloque se ejecuta incondicionalmente. Si el if protegía una validación o una inicialización, el efecto es que ya no protege nada. En el caso de while (cond);, el lazo gira para siempre porque su cuerpo vacío no modifica el estado. No hay ningún warning por defecto.

Fundamento en el estándar C11

ISO/IEC 9899:2011 §6.8.3 define la sentencia nula, y §6.8.4.1 asocia el cuerpo del if a la sentencia inmediatamente siguiente. La cátedra exige llaves en toda estructura de control (regla 0x1001h), lo que hace visible este error y lo vuelve imposible de introducir sin que salte a la vista.

Corrección idiomática

❌ Código con el antipatrón
if (x > 0);
{
    hacer_algo();
}
✅ Código refactorizado
if (x > 0)
{
    hacer_algo();
}

Eliminar el ; restituye el bloque como cuerpo del if; la llave y el estilo Allman dejan el control explícito.

Errores típicos al compilar o ejecutar

Con el antipatrón: el programa compila sin avisos y ejecuta hacer_algo()
aunque x <= 0. No hay mensaje de error que delate la causa.

Al compilar con -Wempty-body:
warning: suggest braces around empty body in an 'if' statement [-Wempty-body]

Checklist de verificación

Reglas relacionadas

Antipatrón: Ambigüedad sintáctica por omisión de llaves en condicional anidado (Dangling Else)

Síntoma en el código del estudiante

Un if interno sin llaves convive con un else cuya indentación (o la intención del autor) sugiere que pertenece al if externo:

if (a)
    if (b)
        foo();
else
    bar();

Diagnóstico

Mecanismo del defecto

La gramática de C asocia cada else con el if no emparejado más cercano (ISO/IEC 9899:2011 §6.8.4.1). Por lo tanto else pertenece a if (b), no a if (a). La indentación no tiene valor sintáctico: el compilador ignora los espacios y aplica la regla del “if colgado”.

Consecuencia observable

Cuando a es falso, bar() no se ejecuta, aunque el autor esperaba lo contrario. Cuando a es verdadero y b falso, sí se ejecuta. El resultado es un bug lógico que depende de la combinación de condiciones, sin ningún error de compilación ni advertencia por defecto.

Fundamento en el estándar C11

ISO/IEC 9899:2011 §6.8.4.1 establece la asociación del else con el if más próximo. La cátedra elimina la ambigüedad con llaves obligatorias en cada nivel condicional (regla 0x1001h), de modo que la estructura escrita coincide con la intención sin depender de la indentación.

Corrección idiomática

❌ Código con el antipatrón
if (a)
    if (b)
        foo();
else
    bar();
✅ Código refactorizado
if (a)
{
    if (b)
    {
        foo();
    }
}
else
{
    bar();
}

Las llaves fijan a qué if pertenece cada else: ahora el else pertenece al if (a) de forma explícita y bar() se ejecuta cuando a es falso.

Errores típicos al compilar o ejecutar

Con -Wdangling-else (incluida en -Wall):
warning: this 'else' clause does not guard... [-Wdangling-else]
note: ...this 'if' clause

Sin la advertencia, el comportamiento es el del 'else' más cercano;
bar() no se ejecuta cuando a es falso.

Checklist de verificación

Reglas relacionadas