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 0x2006h: Mantené el alcance de las variables al mínimo posible

Funciones, contratos y modularizacion (0x20XX)

Universidad Nacional de Río Negro

0x2006h: Mantené el alcance de las variables al mínimo posible

Enunciado normativo

DEBE declararse cada variable en el bloque más pequeño que la contenga y lo más cerca posible de su primer uso. NO DEBE diferirse la declaración al inicio de la función si solo se usa dentro de un lazo o de una rama.

¿Por qué existe esta regla?

El problema

Una variable declarada al inicio está “viva” durante todo el cuerpo aunque solo se use en las últimas líneas: cualquier bloque intermedio puede leerla por error y el lector debe recordar en qué estado está. Cuanto más corta es la ventana entre declaración y uso, menos estado hay que retener. El alcance mínimo también evita el reciclaje accidental, germen de 0x2011h: Prohibición de asignaciones múltiples a una variable sin lectura intermedia (dead store).

Consecuencias de violarla

Tipo de consecuenciaEfecto concreto
Bug silenciosoUn bloque intermedio la usa antes de su inicialización.
MantenibilidadNo se sabe en qué momento el dato cobra sentido.
WarningEl compilador marca variables sin uso o sin inicializar.

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

C11 define el alcance por el bloque donde se declara (§6.2.1): al cerrarlo, la variable deja de existir. Desde C99 se permite declarar en medio del bloque (§6.8.2), así que no hay razón técnica para amontonarlas. La cátedra lo exige porque achica el estado activo; es la versión local de 0x2004h: No se permite el uso de variables globales.

Alcance y excepciones

Aplica a variables locales, incluidas las de los lazos for, que deben declararse en su cláusula de inicialización. Excepción: un struct que se inicializa por partes a lo largo de la función puede declararse al comienzo si todos los usos pertenecen a la misma idea y no hay bloques intermedios.

Ejemplos exhaustivos

❌ Contraejemplo 1 — Declarar arriba y usar al final

int procesar(const int datos[], size_t n)
{
    int suma = 0;
    int maximo = datos[0];
    int min;                 /* declarada y nunca usada */
    for (size_t i = 0; i < n; i++) {
        suma += datos[i];
    }
    /* ... 60 líneas ... */
    for (size_t i = 0; i < n; i++) {
        if (datos[i] > maximo) {
            maximo = datos[i];
        }
    }
    return maximo;
}

min se declara y nunca se usa (0x8001h: Una aserción por cada función de prueba); el retraso entre declaración y uso obliga a recordar variables que no participan.

❌ Contraejemplo 2 — Variable que sobrevive a su propósito

void informe(void)
{
    double promedio = 0.0;
    for (int i = 0; i < CANTIDAD; i++) {
        promedio += leer_nota(i);
    }
    promedio /= CANTIDAD;
    for (int j = 0; j < CANTIDAD; j++) {
        imprimir_nota(j);
    }
}

promedio queda en alcance durante el segundo lazo, donde ya no se usa.

✅ Ejemplo conforme 1 — Alcance de lazo

int maximo(const int datos[], size_t n)
{
    if (n == 0) {
        return ERROR_ARREGLO_VACIO;
    }
    int max = datos[0];
    for (size_t i = 1; i < n; i++) {
        if (datos[i] > max) {
            max = datos[i];
        }
    }
    return max;
}

i existe solo dentro del for y max nace pegado a su primer uso.

✅ Ejemplo conforme 2 — Alcance de bloque condicional

int emitir_factura(const struct pedido_t *p)
{
    if (p->tipo == CONTADO) {
        double descuento = p->total * 0.10;
        return (int)(p->total - descuento);
    }
    if (p->tipo == CREDITO) {
        double recargo = p->total * 0.05;
        return (int)(p->total + recargo);
    }
    return (int)p->total;
}

Cada auxiliar vive solo en la rama que la usa; el descuento no puede filtrarse al camino de crédito.

⚠️ Casos límite

Cómo detectarla

HerramientaComandoSeñal
gaffgaff check archivo.cDeclaración separada de su primer uso.
gcc / clanggcc -Wall -Wextra -Wunused-variable ...Variable sin usar o que oculta otra.

Checklist de autocontrol

Reglas relacionadas

Antipatrón: Variable local declarada pero no utilizada

Síntoma en el código del estudiante

Variables declaradas al inicio de la función que nunca se leen, o que se declaran y se inicializan “por las dudas”. Suelen aparecer junto a índices declarados decenas de líneas antes de su for y a copias de parámetros que nadie usa.

Diagnóstico

Mecanismo del defecto

El estudiante reserva el marco de pila de una variable, le asigna un valor y nunca la lee. El compilador puede eliminar el almacenamiento, pero el lector no: ve el identificador en la cabecera de la función y asume que participa del cálculo. La variable fantasma contamina el modelo mental del que lee, porque no hay forma de saber si su ausencia de uso es intencional o un olvido.

Cuando la variable se declara lejos de su uso, se suma el problema de alcance de 0x2006h: Mantené el alcance de las variables al mínimo posible: la vida útil no coincide con el propósito. Y si el estudiante la reutiliza para otra cosa más abajo, aparece el riesgo de 0x7001h: Siempre debés inicializar las variables a un valor conocido (valor residual).

Consecuencia observable

GCC emite -Wunused-variable para las que nunca se usan y -Wunused-but-set-variable para las que solo se escriben. El resultado es código que parece más complejo de lo que es y, en el peor caso, un cálculo que el autor creía vigente y fue descartado.

Fundamento en el estándar C11

Una variable local con duración automática existe desde su declaración hasta el cierre del bloque (§6.2.4 y §6.2.1). La norma permite declararla sin usarla; el problema es de claridad (0x0001h: La claridad y prolijidad son de máxima importancia) y de esfuerzo de lectura. El estándar no obliga a consumir el objeto, pero la cátedra sí exige que todo identificador declare una intención cumplida.

Corrección idiomática

❌ Código con el antipatrón
int main(void)
{
    int no_usada = 10;
    int i;
    int suma = 0;

    for (i = 0; i < 3; i++) {
        suma += i;
    }

    return 0;
}
✅ Código refactorizado
int main(void)
{
    int suma = 0;

    for (int i = 0; i < 3; i++) {
        suma += i;
    }

    return 0;
}

no_usada desaparece y i nace dentro del for. El estado activo de la función queda reducido a suma, que sí se usa.

Errores típicos al compilar o ejecutar

aviso: variable 'no_usada' definida pero no usada [-Wunused-variable]
aviso: variable 'i' fijada pero no usada [-Wunused-but-set-variable]
error: 'suma' no se usa [-Werror=unused-variable]  (con -Werror)

Checklist de verificación

Reglas relacionadas