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 0x500Fh: Colisión de nombres de macroguardas entre archivos de cabecera distintos

Compilacion, preprocesador y seguridad (0x50XX)

Universidad Nacional de Río Negro

0x500Fh: Colisión de nombres de macroguardas entre archivos de cabecera distintos

Enunciado normativo

NO DEBEN compartir macro de guarda dos cabeceras distintas. El nombre NOMBRE_H DEBE derivar del archivo (idealmente con un prefijo de proyecto) y ser único en toda la unidad de traducción.

¿Por qué existe esta regla?

El problema

La guarda de inclusión usa un macro global a la unidad de traducción. Si lista.h y pila.h usan ambas UTILS_H, al compilar main.c con lista.h primero el preprocesador define UTILS_H y procesa su cuerpo. Cuando llega a pila.h, encuentra el macro ya definido y saltea todo su contenido: ni los prototipos ni los tipos existen. El error aparece en el archivo cliente, a kilómetros de la causa real: no faltan guardas, los nombres están repetidos.

Consecuencias de violarla

Tipo de consecuenciaEfecto concreto
CompilaciónEl segundo encabezado se ignora; tipos y prototipos «desaparecen».
FuncionamientoA veces compila según el orden de los #include, un bug intermitente.
DiagnósticoEl error aparece en el archivo cliente, no en la cabecera culpable.
EscalabilidadSe agrava a medida que el proyecto suma módulos y cabeceras.

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

ISO/IEC 9899:2011 §6.10.1 regula #ifndef/#define/#endif: la inclusión condicional consulta un macro único en la unidad de traducción. La cátedra exige nombres únicos, que son responsabilidad del programador y no del estándar.

Alcance y excepciones

Aplica a todas las cabeceras del proyecto; no hay excepción. Un patrón robusto es prefijar con el proyecto o la carpeta (PROYECTO_LISTA_H) y, ante módulos homónimos, incluir la distinción (SENSORES_LISTA_H). Evitá los prefijos reservados __ y _ + mayúscula (0x010Ah: Prohibición de identificadores con prefijos reservados para el compilador (__ o _[A-Z])).

Ejemplos exhaustivos

❌ Contraejemplo 1 — Misma guarda en dos cabeceras

/* lista.h */
#ifndef UTILS_H
#define UTILS_H
int lista_agregar(int valor);
#endif
/* pila.h */
#ifndef UTILS_H
#define UTILS_H
int pila_apilar(int valor);
#endif

Por qué falla: si main.c incluye lista.h antes que pila.h, esta última se saltea completa y pila_apilar no existe. El error se reporta en main.c.

❌ Contraejemplo 2 — Prefijo reservado y genérico

#ifndef __UTILS_H__
#define __UTILS_H__
/* contenido */
#endif

Por qué falla por dos motivos: el nombre se repite con cualquier otra cabecera utils, y empieza con doble guion bajo, un prefijo reservado a la implementación (0x010Ah: Prohibición de identificadores con prefijos reservados para el compilador (__ o _[A-Z])).

✅ Ejemplo conforme 1 — Guardas derivadas del proyecto

/* lista.h */
#ifndef PROYECTO_LISTA_H
#define PROYECTO_LISTA_H
int lista_agregar(int valor);
#endif
/* pila.h */
#ifndef PROYECTO_PILA_H
#define PROYECTO_PILA_H
int pila_apilar(int valor);
#endif

Cada macro identifica sin ambigüedad a su archivo; incluir ambas cabeceras en cualquier orden produce el mismo resultado.

✅ Ejemplo conforme 2 — Cabeceras homónimas en carpetas distintas

/* sensores/lista.h */
#ifndef SENSORES_LISTA_H
#define SENSORES_LISTA_H
#endif

/* usuarios/lista.h */
#ifndef USUARIOS_LISTA_H
#define USUARIOS_LISTA_H
#endif

Cuando dos módulos tienen un archivo con el mismo nombre, la carpeta forma parte del macro de guarda y ambas interfaces conviven en una misma unidad.

⚠️ Casos límite

Cómo detectarla

HerramientaComandoSeñal
gaffgaff check *.hReporta 0x500Fh al encontrar el mismo macro en dos cabeceras.
gccgcc -H -E archivo.cUna cabecera esperada no aparece procesada.

Checklist de autocontrol

Reglas relacionadas