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 0x2004h: No se permite el uso de variables globales

Funciones, contratos y modularizacion (0x20XX)

Universidad Nacional de Río Negro

0x2004h: No se permite el uso de variables globales

Enunciado normativo

NO DEBE declararse estado mutable con alcance de archivo ni con enlace externo. Los datos compartidos DEBEN viajar como parámetros, o bien encapsularse dentro de un tipo y pasaarse un puntero a ese tipo.

¿Por qué existe esta regla?

El problema

Una variable global es una entrada y una salida invisible de cada función: la firma promete depender solo de sus parámetros, pero el resultado también cambia con modo_global. Cualquier función puede escribirla, así que rastrear quién la modificó obliga a auditar todo el programa. El orden de las llamadas pasa a importar de forma oculta y aparecen bugs no reproducibles.

Consecuencias de violarla

Tipo de consecuenciaEfecto concreto
Bug silenciosoUna función pisa un global que otra función esperaba leer intacto.
TestingLos tests no son independientes: dependen del orden de ejecución.
MantenibilidadPara entender una función hay que leer todo el archivo.

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

En C11 un objeto declarado fuera de toda función tiene duración estática y vive mientras dure el programa (§6.2.4); su enlace puede ser interno (static) o externo (§6.2.2). El estándar lo permite; la cátedra lo prohíbe por el diseño modular de 0x2005h: Cada función debe tener una única responsabilidad (Principio de Responsabilidad Única). La presente endurece a 0x0106h: Las variables globales deben ser declaradas como static o usar prefijo g_.

Alcance y excepciones

Prohíbe el estado mutable: variables que cambian durante la ejecución. Sí se admiten constantes #define (0x0107h: Las macros #define deben nombrarse en MAYUSCULAS_SNAKE_CASE), objetos const de solo lectura con enlace interno (static const) y enum de constantes (0x300Dh: Utilizá enum en lugar de ‘números mágicos’ para conjuntos de estados y valores constantes).

Si hace falta estado compartido, se encapsula en un struct y se pasa por parámetro; el dueño queda explícito en el código.

Ejemplos exhaustivos

❌ Contraejemplo 1 — Contador global compartido

int total_procesados = 0;

void registrar(struct item_t *it)
{
    if (it->valido == true) {
        total_procesados++;
    }
}

Por qué falla: registrar altera un estado que no figura en su firma. Dos pruebas consecutivas dan resultados distintos, y cualquier otro módulo puede leer o pisar total_procesados sin aviso.

❌ Contraejemplo 2 — Configuración global dispersa

int modo_debug = 1;
const char *ruta_salida = "salida.txt";

void escribir(const char *texto)
{
    if (modo_debug == 1) {
        fprintf(stderr, "[debug] %s\n", texto);
    }
    /* usa ruta_salida directamente */
}

Por qué falla: la función depende de dos globales que no recibe ni documenta. No se puede probar en modo silencioso ni redirigir la salida sin tocar el estado del proceso entero.

✅ Ejemplo conforme 1 — Estado encapsulado y pasado por parámetro

struct contador_t {
    size_t total;
};

void registrar(struct contador_t *c, const struct item_t *it)
{
    if (it != NULL && it->valido == true) {
        c->total++;
    }
}

El estado viaja como parámetro. La firma dice exactamente de qué depende y qué modifica; el dueño es quien declaró la variable.

✅ Ejemplo conforme 2 — Constante de configuración inmutable

#define BUFFER_MAX 1024
#define RUTA_SALIDA "salida.txt"

static const double PI = 3.141592653589793;

double area_circulo(double radio)
{
    return PI * radio * radio;
}

PI, BUFFER_MAX y RUTA_SALIDA no cambian durante la ejecución, así que no son estado compartido. El prefijo static restringe PI a la unidad de traducción y evita colisiones de enlace.

⚠️ Casos límite

Cómo detectarla

HerramientaComandoSeñal
gaffgaff check archivo.cVariable mutable fuera de función.
gcc / clanggcc -Wall -Wextra -Wshadow -std=c11 ...Uso de un objeto no local sin pasarlo por parámetro.
Revisión manualFirma que omite una entrada que la función realmente lee.

Checklist de autocontrol

Reglas relacionadas