Regla 0x301Bh: Prohibición de casts de tipo innecesarios o redundantes
Memoria, punteros y tipos (0x30XX)
0x301Bh: Prohibición de casts de tipo innecesarios o redundantes¶
Enunciado normativo¶
NO DEBEN escribirse conversiones de tipo (
cast) cuando el operando ya tiene el tipo destino o cuando la conversión la realiza el compilador sin pérdida de información. El cast DEBE reservarse para conversiones reales que el autor necesita documentar.
¿Por qué existe esta regla?¶
El problema¶
Un cast agrega ruido sintáctico y, peor, puede mentir. (int)0 no convierte
nada: el literal 0 ya es int. (double)contador sobre una variable double
no cambia nada. Estos casts hacen que el lector busque una razón que no existe.
El cast tampoco es inocuo cuando silencia una advertencia legítima: (int)x
sobre un double puede esconder un truncamiento. Cada cast debería ser una
decisión consciente y visible, no una costumbre.
Consecuencias de violarla¶
| Tipo de consecuencia | Efecto concreto |
|---|---|
| Ruido visual | La atención se gasta en operadores que no hacen nada. |
| Advertencias silenciadas | Un cast tapa el warning de conversión con pérdida. |
| Mantenibilidad | Al cambiar el tipo de una variable, el cast viejo queda incoherente. |
| Falsa precisión | El lector cree que hay una conversión donde no la hay. |
Fundamento en el estándar y en la cátedra¶
ISO/IEC 9899:2011 §6.5.4 define el operador de conversión explícita. El estándar lo permite siempre que los tipos sean compatibles; la cátedra lo restringe a las conversiones reales. Se apoya en 0x5009h: Prohibición de división entera no intencional asignada a flotantes (división entera asignada a flotante) y en 0x301Ah: Validador de uso idiomático de tipos booleanos estándar para los casos donde la conversión sí importa.
Alcance y excepciones¶
Casts permitidos: conversión entre tipos de puntero según 0x300Ah: Utilizá cast explícito al convertir tipos de punteros, paso a
void *para memoria genérica, y conversiones aritméticas reales como(double)suma / (double)n.Casts prohibidos: al mismo tipo, a un tipo que ya contiene al operando, o literales con sufijo innecesario.
No confundir con
sizeofni con conversiones de argumentos variádicos.
Ejemplos exhaustivos¶
❌ Contraejemplo 1 — cast de un literal al mismo tipo¶
int x = (int)0;
double y = (double)3.5;Por qué falla: 0 ya es int y 3.5 ya es double. Los casts no convierten
nada y obligan al lector a preguntarse si había una razón oculta.
❌ Contraejemplo 2 — cast que tapa un truncamiento¶
double promedio = (double)calcular_entero();Por qué falla: si calcular_entero ya devuelve double, el cast sobra; si
devuelve int, el cast es real pero la división posterior puede seguir siendo
entera según el contexto. El cast aislado no garantiza el resultado esperado.
✅ Ejemplo conforme 1 — sin casts redundantes¶
int x = 0;
double y = 3.5;El tipo del literal ya coincide con el de la variable; la asignación es directa y no hay operador que analizar.
✅ Ejemplo conforme 2 — cast real y necesario¶
double promedio(const int valores[], size_t n)
{
if (n == 0)
{
return 0.0;
}
int suma = 0;
for (size_t i = 0; i < n; i++)
{
suma += valores[i];
}
return (double)suma / (double)n;
}Acá el cast es imprescindible: sin él, suma / n sería una división entera
truncada antes de llegar al return (ver 0x5009h: Prohibición de división entera no intencional asignada a flotantes).
⚠️ Casos límite¶
Conversión de signo:
(unsigned)xsobre unintnegativo es una conversión real; documentarla con un comentario.malloc: el cast(int *)malloc(...)está prohibido por otra razón (ver 0x300Bh: Usá siempre sizeof en las asignaciones de memoria dinámica, prefiriendo sizeof(*ptr) y 0x3013h: Asignación de memoria con sizeof sobre puntero en lugar del tipo apuntado).Literales con sufijo:
10.0fes correcto;(float)10.0también pero redundante si ya se buscafloat.
Cómo detectarla¶
| Herramienta | Comando | Señal |
|---|---|---|
gaff | gaff check archivo.c | Regla 0x301Bh: cast redundante (autofix). |
gcc | gcc -Wall -Wextra -Wconversion | Avisos de conversiones con y sin cast. |
| Revisión manual | — | (tipo) cuyo operando ya es de ese tipo. |
Checklist de autocontrol¶
¿Algún cast convierte a un tipo que el operando ya tiene?
¿Cada cast que queda documenta una conversión real?
¿El cast no silencia una advertencia importante?
¿La división que quiero flotante tiene realmente el cast en el lugar correcto?
Reglas relacionadas¶
0x5009h: Prohibición de división entera no intencional asignada a flotantes — la división entera asignada a flotante trunca sin aviso.
0x300Ah: Utilizá cast explícito al convertir tipos de punteros — los cast de punteros deben ser explícitos y reales.
0x3013h: Asignación de memoria con sizeof sobre puntero en lugar del tipo apuntado — no usar
sizeofsobre el puntero en lugar del tipo apuntado.