Regla 0x5014h: Inclusión explícita obligatoria de cabeceras para funciones de biblioteca estándar
Compilacion, preprocesador y seguridad (0x50XX)
0x5014h: Inclusión explícita obligatoria de cabeceras para funciones de biblioteca estándar¶
Enunciado normativo¶
DEBE incluirse la cabecera oficial de cada función estándar usada y NO DEBE depender de declaraciones implícitas. Si una función no tiene prototipo en alcance, el código no compila con
-std=c11 -Werror.
¿Por qué existe esta regla?¶
El problema¶
Esta regla es el complemento operativo de 0x500Bh: Inclusión obligatoria de cabeceras estándar para funciones de la biblioteca C: allí se mapea función
→ cabecera; acá se prohíbe el patrón que la omisión habilita, la declaración
implícita. En C89, llamar sin prototipo hacía que el compilador asumiera
int f() y no verificara argumentos; C99 eliminó esa regla y C11 exige una
declaración en alcance. El peligro es que el tipo asumido (int) casi nunca
coincide con el real: strlen devuelve size_t, malloc un void * y sqrt
un double; interpretarlos como int corrompe el resultado.
Consecuencias de violarla¶
| Tipo de consecuencia | Efecto concreto |
|---|---|
| Comportamiento indefinido | malloc sin <stdlib.h> devuelve int; el puntero se trunca. |
| Bug silencioso | strlen sin <string.h> pierde los 32 bits altos de size_t. |
| Compilación | implicit declaration es error en GCC moderno con -Werror. |
Fundamento en el estándar y en la cátedra¶
ISO/IEC 9899:2011 §6.5.2.2 exige que la función tenga una declaración en alcance
para que la llamada sea válida; §6.9 regula las declaraciones en las cabeceras.
La cátedra compila con gcc -std=c11 -Wall -Wextra -Werror -pedantic, perfil en
el que cualquier declaración implícita aborta la compilación.
Alcance y excepciones¶
Aplica a funciones estándar y a funciones propias: si main.c invoca
mi_funcion definida en otro .c, debe incluir su .h (0x5011h: Prohibición de declaraciones extern en archivos de implementación (.c)).
Excepción de enlace: <math.h> declara la función, pero en Linux hay que
agregar -lm; la cabecera no reemplaza la biblioteca.
Ejemplos exhaustivos¶
❌ Contraejemplo 1 — sqrt sin <math.h>¶
int main(void)
{
double r = sqrt(2.0);
printf("%f\n", r);
return 0;
}Por qué falla: sin <math.h> el compilador asume que sqrt devuelve int, de
modo que 1.4142 se trunca a 1 y luego se convierte a double. El cálculo es
silenciosamente incorrecto.
❌ Contraejemplo 2 — Función propia sin prototipo¶
int main(void)
{
return calcular(2, 3);
}Por qué falla: calcular no está declarada antes de main. Aunque su
definición aparezca después en otro archivo, este .c no ve el prototipo; el
compilador asume una firma y no valida los argumentos. La solución es incluir
calculo.h.
✅ Ejemplo conforme 1 — Cabeceras explícitas para cada función¶
#include <math.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
const char *texto = "2.0";
double r = sqrt(2.0);
size_t n = strlen(texto);
printf("%f %zu\n", r, n);
return 0;
}Cada función tiene su prototipo: sqrt en <math.h>, printf en <stdio.h> y
strlen (que devuelve size_t) en <string.h>. El compilador valida tipos y
formatos, y el enlace agrega -lm para la función matemática.
✅ Ejemplo conforme 2 — Prototipo propio en la cabecera¶
/* calculo.h */
#ifndef CALCULO_H
#define CALCULO_H
int calculo_sumar(int a, int b);
#endif/* main.c */
#include "calculo.h"
int main(void)
{
return calculo_sumar(2, 3);
}La interfaz propia se declara en su cabecera y se incluye antes de usar. Así el
mismo control que rige para <stdio.h> vale para las funciones de la materia y
el compilador detecta cualquier discrepancia de firma.
⚠️ Casos límite¶
<math.h>y-lm: la declaración no garantiza el enlace; falta-lm.Tipos estándar:
size_tproviene de<stddef.h>, no de<string.h>.
Cómo detectarla¶
| Herramienta | Comando | Señal |
|---|---|---|
gaff | gaff check archivo.c | Reporta 0x5014h ante una llamada sin prototipo en alcance. |
gcc / clang | gcc -std=c11 -Wall -Wextra -Werror -pedantic archivo.c | implicit declaration of function 'sqrt'. |
Checklist de autocontrol¶
¿Cada función estándar tiene su cabecera incluida en este archivo?
¿Cada función propia tiene un prototipo visible por su
.h?¿Agregué
-lmsi uso funciones de<math.h>?
Reglas relacionadas¶
0x500Bh: Inclusión obligatoria de cabeceras estándar para funciones de la biblioteca C — el mapeo entre cada función y su cabecera.
0x0205h: En archivos .c la inclusión de la cabecera propia debe figurar en primer lugar — la cabecera propia primero revela qué declaraciones faltan.