Regla 0x5007h: Inclusiones redundantes o duplicadas de la misma cabecera #include
Compilacion, preprocesador y seguridad (0x50XX)
0x5007h: Inclusiones redundantes o duplicadas de la misma cabecera #include¶
Enunciado normativo¶
NO DEBE incluirse dos veces la misma cabecera en una misma unidad de traducción, salvo el patrón deliberado de X-macros o el re-
#includede<assert.h>para cambiarNDEBUG.
¿Por qué existe esta regla?¶
El problema¶
Cada #include es una copia textual que hace el preprocesador antes de
compilar. Si una cabecera aparece dos veces, el cuerpo se procesa dos veces; con
guardas el efecto es nulo, pero el archivo queda con ruido, revela copias y
pegados descuidados y encarece la compilación. Además, una inclusión duplicada
sin guarda produce redefiniciones y errores que el lector atribuye a la cabecera
cuando el problema es la duplicación.
Detectarlo es barato y automatizable, y su presencia suele señalar desorden: cabeceras repetidas en distintas secciones o tras un refactor a medias.
Consecuencias de violarla¶
| Tipo de consecuencia | Efecto concreto |
|---|---|
| Compilación | Sin guarda, redefinition of ...; con guarda, silencio y solo ruido. |
| Tiempo de compilación | Cada duplicación vuelve a abrir y parsear el encabezado. |
| Mantenibilidad | Señal de copia/pegado o de includes dispersos. |
| Auditoría | Dificulta ver de un vistazo qué depende realmente el archivo. |
Fundamento en el estándar y en la cátedra¶
ISO/IEC 9899:2011 §6.10.2 define la directiva #include y su efecto de copia.
El estándar permite incluir una cabecera más de una vez; por eso la regla es de
estilo y no de conformidad. La cátedra la exige porque -Wall no la detecta y
gaff la corrige con autofix, eliminando una fuente habitual de ruido en las
entregas.
Alcance y excepciones¶
Aplica a toda unidad de traducción (.c o .h). Excepciones legítimas:
X-macros: un archivo
.defse incluye dos veces con#definedistintos para generar, por ejemplo, unenumy una tabla de nombres.<assert.h>: puede re-incluirse tras definir o indefinirNDEBUGpara habilitar o deshabilitar las aserciones, como permite §7.2.Inclusiones condicionales: dos
#includede la misma cabecera en ramas mutuamente excluyentes de un#ifdefno coexisten en una compilación.
Ejemplos exhaustivos¶
❌ Contraejemplo 1 — Cabecera repetida en el bloque de includes¶
#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
printf("ok\n");
return 0;
}Por qué falla: <stdio.h> aparece dos veces. Con guardas compila, pero es ruido
puro; gaff fix elimina la segunda y deja el bloque limpio.
❌ Contraejemplo 2 — Duplicación escondida tras refactor¶
#include "lista.h"
#include "pila.h"
#include "lista.h"Por qué falla: al agregar pila.h se volvió a pegar el #include anterior. La
segunda línea no aporta nada y engaña sobre las dependencias reales del archivo.
✅ Ejemplo conforme 1 — Bloque de includes único y ordenado¶
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lista.h"
#include "pila.h"Cada cabecera aparece una sola vez, con las estándar primero. Es además el orden que pide 0x5005h: Organizá la estructura de tus archivos .c de forma estándar.
✅ Ejemplo conforme 2 — X-macro, duplicación intencional documentada¶
#define COLOR(nombre, valor) nombre,
typedef enum {
#include "colores.def"
CANTIDAD_COLORES
} color_t;
#undef COLOR
#define COLOR(nombre, valor) { #nombre, valor },
static const struct {
const char *nombre;
int valor;
} tabla_colores[] = {
#include "colores.def"
};
#undef COLORcolores.def se incluye dos veces a propósito, con COLOR redefinida entre
medio, para generar el enum y la tabla. Es la excepción canónica a esta regla.
⚠️ Casos límite¶
Guarda presente: la duplicación no rompe, pero sigue siendo una violación.
Dos cabeceras homónimas:
#include "a/util.h"y#include "b/util.h"son archivos distintos; no cuentan como duplicación.<assert.h>conNDEBUG: permitido aunque el texto sea idéntico.
Cómo detectarla¶
| Herramienta | Comando | Señal |
|---|---|---|
gaff | gaff check archivo.c | Reporta 0x5007h por cada #include repetido; gaff fix elimina los duplicados. |
gcc | gcc -E archivo.c | El encabezado aparece expandido dos veces. |
Checklist de autocontrol¶
¿Cada cabecera aparece una sola vez en el archivo?
¿Agrupé los includes por sección y no los repetí al pegar código?
Si dupliqué a propósito (X-macro o assert), ¿lo documenté?
¿Corrí
gaff fixantes de entregar para desduplicar automáticamente?
Reglas relacionadas¶
0x5003h: Utilizá guardas de inclusión en todos los archivos de cabecera — la guarda evita que una duplicación provoque errores.
0x5005h: Organizá la estructura de tus archivos .c de forma estándar — el bloque de includes es la primera sección del orden canónico.