Regla 0x300Ah: Utilizá cast explícito al convertir tipos de punteros
Memoria, punteros y tipos (0x30XX)
0x300Ah: Utilizá cast explícito al convertir tipos de punteros¶
Enunciado normativo¶
Toda conversión entre tipos de puntero DEBE escribirse con un cast explícito. NO DEBE agregarse cast cuando la conversión es implícita y segura, en particular sobre el retorno de
malloc,callocorealloc.
¿Por qué existe esta regla?¶
El problema¶
C es permisivo con las conversiones de punteros, pero no todas son equivalentes.
Convertir un void * a cualquier T * es implícito y seguro: void * es el
puntero genérico y el asignador lo devuelve así. Convertir entre T1 * y T2 *
con tipos incompatibles no es un ajuste de tipo, sino una reinterpretación del
contenido, y desreferenciar el resultado viola las reglas de aliasing.
El cast explícito hace visible cuál de las dos cosas está ocurriendo. Sin él, el lector no distingue una conversión inocua de una peligrosa, y el compilador puede pasar por alto diagnósticos útiles. La regla exige ser explícito donde la conversión es real, y no agregar ruido donde no lo es.
Consecuencias de violarla¶
| Tipo de consecuencia | Efecto concreto |
|---|---|
| Bug silencioso | Un cast oculta tipos incompatibles y el error aparece en ejecución. |
| Comportamiento indefinido | Desreferenciar el resultado viola strict aliasing (C11 §6.5 párr. 7). |
| Portabilidad | Los casts sobre malloc esconden la falta de #include <stdlib.h>. |
| Legibilidad | No se distingue conversión intencional de error de tipos. |
Fundamento en el estándar y en la cátedra¶
C11 §6.5.4 define el operador de conversión. C11 §6.3.2.3 permite convertir
implícitamente entre un puntero de objeto y void * (ida y vuelta). La cátedra
pide la forma explícita sólo para conversiones entre tipos de puntero distintos
de void *, y prohíbe el cast redundante en la reserva para que el compilador
delate la ausencia de la cabecera (ver 0x300Ah: Utilizá cast explícito al convertir tipos de punteros). Es el punto
de equilibrio entre claridad y seguridad.
Alcance y excepciones¶
Aplica a conversiones explícitas entre T1 * y T2 *, entre punteros y
enteros, y entre punteros a función. Excepción: la conversión implícita
void * ⇄ T * no requiere ni admite cast; escribir
int *p = (int *)malloc(n * sizeof(*p)); agrega un cast redundante que la
cátedra desaconseja. Tampoco se requiere cast al pasar T * a un parámetro
void *.
Ejemplos exhaustivos¶
❌ Contraejemplo 1 — Conversión implícita entre punteros incompatibles¶
unsigned char *bytes = obtener_buffer();
int *valores = bytes;Por qué falla: int * y unsigned char * son tipos de objeto distintos; la
asignación es una violación de restricción que el compilador advierte con
-Wincompatible-pointer-types. Al desreferenciar valores, el acceso a un
objeto de tipo int a través de un lvalue de otro tipo (o viceversa) viola las
reglas de aliasing. Si la conversión es deliberada (reinterpretar bytes), debe
ser explícita y documentada.
❌ Contraejemplo 2 — Cast redundante que esconde una cabecera faltante¶
#include <stdio.h>
double *datos = (double *)malloc(10 * sizeof(*datos));Por qué falla: falta #include <stdlib.h>, de modo que malloc se declara
implícitamente como función que retorna int. Sin el cast, el compilador avisa
de la conversión de int a puntero; con el cast, el aviso desaparece y en
plataformas de 64 bits la dirección puede truncarse. El cast tapa el diagnóstico
en lugar de resolver la causa.
✅ Ejemplo conforme 1 — Conversión explícita deliberada¶
unsigned char *bytes = obtener_buffer();
int *valores = (int *)bytes;El cast deja claro que se está reinterpretando la memoria. Quien lo lea sabrá
que el acceso a *valores sólo es válido si los bytes están correctamente
alineados y contienen un int; ambas condiciones deben documentarse. La
conversión es visible y auditable.
✅ Ejemplo conforme 2 — Reserva sin cast redundante¶
int *valores = malloc(10 * sizeof(*valores));
if (valores == NULL)
{
return -1;
}malloc devuelve void *, que se convierte implícitamente a int *. No hace
falta cast y su ausencia permite que el compilador detecte un stdlib.h
faltante. La verificación de 0x3001h: Siempre verificá la asignación exitosa de memoria dinámica queda en la línea siguiente.
⚠️ Casos límite¶
Punteros a función:
void (*f)(void) = (void (*)(void))algo;sí requiere cast explícito; las conversiones entre punteros a función y a objeto no son portables.Alineación: convertir
char *aint *y desreferenciar puede fallar si la dirección no está alineada; el cast no arregla la alineación.Enteros y punteros:
(int *)0x1000es sintaxis de sistemas embebidos, no de esta cátedra; ver 0x300Ah: Utilizá cast explícito al convertir tipos de punteros.
Cómo detectarla¶
| Herramienta | Comando | Señal |
|---|---|---|
gaff | gaff check archivo.c | Conversión implícita entre tipos de puntero; cast redundante sobre malloc/free. |
gcc / clang | gcc -Wall -Wextra -std=c11 -Wcast-qual -Wstrict-aliasing ... | incompatible-pointer-types, cast discards const, strict-aliasing. |
cppcheck | cppcheck --enable=all archivo.c | C-style pointer casting sin justificación. |
Checklist de autocontrol¶
¿La conversión es entre tipos de puntero distintos de
void *? Entonces, cast explícito.¿Es el retorno de
malloc? Entonces, sin cast.¿Incluí
<stdlib.h>antes de usar el asignador?¿La dirección convertida está alineada para el tipo destino?
¿Documenté por qué la reinterpretación es válida?
Reglas relacionadas¶
0x3013h: Asignación de memoria con sizeof sobre puntero en lugar del tipo apuntado — el cast no corrige un
sizeofmal calculado.0x3011h: Si una función recibe un puntero genérico para operaciones de solo lectura, la firma de la función debe utilizar const void* — el
constperdido por un cast avisa de un contrato roto.0x3001h: Siempre verificá la asignación exitosa de memoria dinámica — la verificación de la reserva acompaña siempre a la conversión.
0x3017h: Orden canónico de calificadores: ‘const tipo’ en lugar de ‘tipo const’ — ubicación canónica de
consten las conversiones.
Antipatrón: Casteo redundante de malloc()¶
Síntoma en el código del estudiante¶
Toda reserva viene precedida por un molde de tipo sobre malloc, calloc o
realloc:
int *p = (int *)malloc(sizeof(int) * 10);
nodo_t *n = (nodo_t *)malloc(sizeof(nodo_t));El casteo se copia por inercia, muchas veces heredado de ejemplos de C++ o de materiales antiguos.
Diagnóstico¶
Mecanismo del defecto¶
En C, void * se convierte implícitamente a cualquier puntero a objeto y
viceversa (§6.3.2.3p1). El cast no agrega ninguna conversión necesaria: repite
la que el compilador ya haría. Peor aún, si falta #include <stdlib.h>, C89 y
C99 asumen que malloc retorna int; el cast explícito silencia la
advertencia del compilador y en una arquitectura de 64 bits trunca la dirección
a 32 bits, corrompiendo el puntero.
Es decir: el cast no solo es redundante, es activamente peligroso porque tapa
el síntoma (la declaración implícita) que debería delatar un #include
faltante.
Consecuencia observable¶
Código ruidoso que sugiere una conversión que no existe.
Pérdida de la advertencia
implicit declaration of function 'malloc'.En sistemas de 64 bits, punteros truncados y corrupción de heap al usar el resultado (ver
0x300Ah).
Fundamento en el estándar C11¶
C11 §6.3.2.3p1: un puntero a
voidpuede convertirse a puntero a objeto y viceversa sin cast; el resultado compara igual al original.C11 §7.22.3p1:
mallocretornavoid *; no hay tipo concreto que castear.La regla 0x300Ah exige cast explícito cuando la conversión es entre tipos de puntero incompatibles (por ejemplo
char *astruct T *), no cuando el origen ya esvoid *. La cátedra adoptasizeof(*ptr)como forma canónica (regla 0x300Bh) justamente para no repetir el tipo.
Corrección idiomática¶
❌ Código con el antipatrón¶
int *p = (int *)malloc(sizeof(int) * 10);
if (p == NULL) {
return NULL;
}✅ Código refactorizado¶
int *p = malloc(10 * sizeof(*p));
if (p == NULL) {
return NULL;
}✅ Cast que sí corresponde — conversión entre tipos incompatibles¶
void *generico = obtener_bloque();
nodo_t *n = (nodo_t *)generico;Acá el cast documenta una conversión real entre tipos de objeto distintos y es el caso que la regla 0x300Ah sí exige.
⚠️ Casos límite¶
Compilar como C++ no es excusa: la cátedra es C11 y el cast de
mallocen C++ es obligatorio por otras razones; no se traslada a C.El cast no reemplaza la verificación de
NULLni el uso desizeof(*ptr).Castear el retorno de
realloctiene el riesgo adicional de perder el puntero original (ver0x3015h).
Errores típicos al compilar o ejecutar¶
# Sin <stdlib.h> y con cast, el compilador no avisa:
$ gcc -Wall -Wextra -std=c11 programa.c
programa.c:5:14: warning: implicit declaration of function 'malloc'
# el cast (int *) silencia el aviso en compiladores permisivos
$ ./programa
# posible truncamiento en 64 bits: puntero inválido
Segmentation fault (core dumped)Checklist de verificación¶
¿Eliminé los
(tipo *)delante demalloc,callocyrealloc?¿El código incluye
<stdlib.h>?¿Uso
sizeof(*ptr)en lugar de repetir el tipo?¿Reservo el cast explícito para conversiones reales entre punteros incompatibles?
Reglas relacionadas¶
0x300Ah: Utilizá cast explícito al convertir tipos de punteros — cast explícito solo cuando la conversión lo requiere.
0x300Bh: Usá siempre sizeof en las asignaciones de memoria dinámica, prefiriendo sizeof(*ptr) — preferir
sizeof(*ptr)en la reserva.0x500Bh: Inclusión obligatoria de cabeceras estándar para funciones de la biblioteca C — inclusión obligatoria de cabeceras estándar.
0x300Ah: Utilizá cast explícito al convertir tipos de punteros — el caso peligroso.
0x300Ah: Utilizá cast explícito al convertir tipos de punteros — mismo vicio en
free.
Antipatrón: Casteo redundante en invocación de free()¶
Síntoma en el código del estudiante¶
La llamada a free lleva un molde a void *:
free((void *)ptr);A veces el cast se escribe a un tipo concreto ((int *), (nodo_t *)) y otras
a void *. En cualquier caso, es un molde sobre un argumento que ya se
convierte solo.
Diagnóstico¶
Mecanismo del defecto¶
free recibe un void *. Al pasarle un puntero a cualquier tipo de objeto, el
compilador aplica la conversión implícita de §6.3.2.3p1: no hace falta cast. El
molde, entonces, no convierte nada: solo agrega ruido y sugiere una operación
que no existe.
Hay un matiz de estilo además: la regla 0x300Ah exige cast explícito para
conversiones reales entre tipos de puntero incompatibles. Aquí no hay tal
conversión, porque el destino es void *. Escribir free((int *)ptr) tampoco
aporta: free vuelve a convertir a void * inmediatamente.
Consecuencia observable¶
Código más verboso sin ganancia semántica.
Falsa sensación de que el cast “arregla” algo (por ejemplo, un tipo mal declarado), cuando solo lo disimula.
Inconsistencia con el resto del código, que libera sin cast.
Fundamento en el estándar C11¶
C11 §6.3.2.3p1: conversión implícita entre
void *y punteros a objeto.C11 §7.22.3.3p1:
freedeclara su único parámetro comovoid *.C11 §6.5.2.2: las restricciones de la llamada permiten el paso sin cast, ya que la conversión es válida.
Corrección idiomática¶
❌ Código con el antipatrón¶
free((void *)ptr);
free((nodo_t *)nodo);✅ Código refactorizado¶
free(ptr);
ptr = NULL;
free(nodo);
nodo = NULL;Sin cast y con anulación posterior del puntero, según la regla 0x3002h.
✅ Cast legítimo de otra operación¶
void *bloque = malloc(sizeof(nodo_t));
nodo_t *n = (nodo_t *)bloque; /* conversión real de void* a tipo concreto */Nótese la diferencia: acá el cast documenta el tipo con el que se va a usar el
bloque, no un adorno alrededor de free.
⚠️ Casos límite¶
Castear a
void *un puntero a función es incorrecto: la conversión entre punteros a objeto y punteros a función no está garantizada por el estándar, con o sin cast.freesobre unconst char *requiere descartarconst; la cátedra prefiere no liberar a través de punterosconsty mantener la propiedad en el tipo original.El cast no reemplaza la verificación de que el bloque provenga del heap.
Errores típicos al compilar o ejecutar¶
# El cast a void* no genera ninguna advertencia ni error;
# el problema es de estilo:
$ gcc -Wall -Wextra -std=c11 programa.c
# sin diagnóstico por el cast innecesarioChecklist de verificación¶
¿Eliminé el
(void *)(y cualquier otro molde) delante defree?¿Anulé el puntero después de liberarlo (regla 0x3002h)?
¿Reservo los casts para conversiones reales entre tipos de objeto?
¿Evité usar
freesobre punteros a función o conconst?
Reglas relacionadas¶
0x300Ah: Utilizá cast explícito al convertir tipos de punteros — cast explícito solo para conversiones necesarias.
0x3002h: Liberá siempre la memoria dinámica y asigná NULL al puntero para mitigar punteros colgantes — liberar y anular el puntero.
0x300Ah: Utilizá cast explícito al convertir tipos de punteros — mismo vicio en la reserva.
0x300Ah: Utilizá cast explícito al convertir tipos de punteros — el cast peligroso.
Antipatrón: Casteo forzado entre punteros de tipos incompatibles (Violación de Strict Aliasing)¶
Síntoma en el código del estudiante¶
Se toma la dirección de un objeto y se reinterpreta con un puntero a un tipo distinto, para “ver los bits”:
float f = 1.0f;
int *pi = (int *)&f;
printf("%d\n", *pi);El cast fuerza la lectura de un float como si fuera int.
Diagnóstico¶
Mecanismo del defecto¶
C11 §6.5p7 fija qué tipos pueden acceder a un objeto almacenado: el tipo
efectivo del objeto, versiones calificadas, un tipo compatible, un agregado que
lo contenga, o un tipo de carácter. Un float accedido a través de un int *
no cumple ninguna de esas condiciones: es comportamiento indefinido
(violación de strict aliasing).
El compilador asume que punteros a tipos incompatibles no apuntan a la misma memoria. Con optimizaciones, puede reordenar una escritura y una lectura que el programador creía dependientes, o descartar una relectura por considerarla invariante. El resultado cambia según el nivel de optimización.
Consecuencia observable¶
En
-O0suele dar el valor esperado; en-O2aparece un resultado distinto.El mismo código produce salidas diferentes entre compiladores.
-Wstrict-aliasingpuede advertir, pero no siempre; el diagnóstico no es confiable.Formalmente, cualquier comportamiento: desde un valor erróneo hasta una caída.
Fundamento en el estándar C11¶
C11 §6.5p7: regla de aliasing; limita los lvalue válidos para acceder al objeto almacenado.
C11 §6.5.4-6.5.5: la conversión de punteros entre tipos incompatibles es permitida como valor, pero su desreferencia queda sujeta a §6.5p7.
C11 §7.24.2.1:
memcpycopia bytes entre objetos sin imponer restricciones de tipo; es la vía conforme para type punning.C11 §6.5.2.3p3 (nota): una
unionpermite reinterpretar representaciones de forma definida en la práctica.La regla 0x300Ah exige que los casts de punteros sean explícitos y que expresen conversiones legítimas, no reinterpretaciones arbitrarias.
Corrección idiomática¶
❌ Código con el antipatrón¶
float f = 1.0f;
int *pi = (int *)&f;
int bits = *pi; /* violación de strict aliasing */✅ Código refactorizado con memcpy¶
#include <string.h>
float f = 1.0f;
int bits;
memcpy(&bits, &f, sizeof(bits));memcpy copia la representación de bytes sin aliasing: es la operación
explícitamente bendecida por el estándar.
✅ Alternativa con union¶
union {
float como_float;
int como_int;
} u;
u.como_float = 1.0f;
int bits = u.como_int;La union comparte almacenamiento y la reinterpretación queda contenida en un
tipo agregador.
⚠️ Casos límite¶
Acceder a cualquier objeto a través de
char *ounsigned char *sí está permitido por §6.5p7: es la base dememcpy.memcpycon solapamiento no está permitido; para rangos que se pisan existememmove.El aliasing suele calcularse con optimizaciones altas; probar solo en
-O0no demuestra que el código sea conforme.
Errores típicos al compilar o ejecutar¶
$ gcc -O0 -std=c11 programa.c && ./programa
1065353216
$ gcc -O2 -std=c11 programa.c && ./programa
0
$ gcc -O2 -Wstrict-aliasing=2 -std=c11 programa.c
programa.c:3:16: warning: dereferencing type-punned pointer will break
strict-aliasing rulesChecklist de verificación¶
¿Evité desreferenciar un puntero casteado a un tipo incompatible?
¿Usé
memcpy(ounion) para reinterpretar representaciones?¿El código da el mismo resultado en
-O0y en-O2?¿Reservo
char */unsigned char *para inspeccionar bytes?
Reglas relacionadas¶
0x300Ah: Utilizá cast explícito al convertir tipos de punteros — casts explícitos y legítimos entre punteros.
0x3007h: Los argumentos de tipo puntero deben ser const siempre que la función no los modifique —
consten parámetros que no se modifican.0x300Ah: Utilizá cast explícito al convertir tipos de punteros — otro cast mal entendido.
0x300Ah: Utilizá cast explícito al convertir tipos de punteros — conversión forzada de otro dominio.
Antipatrón: Casteo de retorno de malloc() con omisión de include stdlib.h¶
Síntoma en el código del estudiante¶
Falta #include <stdlib.h> y el cast explícito “arregla” el aviso:
int *p = (int *)malloc(sizeof(int));El archivo no incluye la cabecera, pero el cast hace que el código compile sin reclamos.
Diagnóstico¶
Mecanismo del defecto¶
Sin prototipo de malloc, el compilador antiguo asume la regla de C89: una
función no declarada retorna int. Es una declaración implícita, que en
C99/C11 es además una restricción diagnóstica. El cast (int *) convierte ese
int presumido en un puntero, y así silencia la advertencia que delataría
la falta de #include.
El problema es de tamaño: si el compilador asume un retorno int de 32 bits y
la dirección real tiene 64 bits, los 32 bits altos se descartan. El puntero
resultante es una dirección truncada que, al desreferenciar, apunta a cualquier
parte. El comportamiento es indefinido y la portabilidad nula.
En C99/C11 el compilador debe avisar igual por la llamada implícita; pero muchos entornos con configuración laxa lo toleran, y el cast impide ver el problema subyacente.
Consecuencia observable¶
Con
-std=c11 -pedantic-errorsel código no compila (implicit declaration).En compiladores permisivos compila pero trunca la dirección en 64 bits.
Segmentation faultal usar el puntero, con pinta de “misterioso”.
Fundamento en el estándar C11¶
C11 §6.5.2.2p1: una función debe declararse antes de llamarla.
C11 §7.22.3p1:
mallocse declara en<stdlib.h>y retornavoid *.C11 §6.3.2.3p1: la conversión implícita de
void *a puntero a objeto no necesita cast; el cast es puro ruido que oculta el diagnóstico.La regla 0x500Bh exige incluir la cabecera de toda función estándar.
Corrección idiomática¶
❌ Código con el antipatrón¶
/* falta #include <stdlib.h> */
int *p = (int *)malloc(sizeof(int));
*p = 42;✅ Código refactorizado¶
#include <stdlib.h>
int *p = malloc(sizeof(*p));
if (p == NULL) {
return NULL;
}
*p = 42;Incluir la cabecera y quitar el cast resuelve las dos caras del mismo error.
✅ Ejemplo conforme adicional — cabeceras completas¶
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int *p = malloc(10 * sizeof(*p));
if (p == NULL) {
return 1;
}
free(p);
p = NULL;
return 0;
}Las funciones de biblioteca usadas tienen su cabecera: malloc y free
(<stdlib.h>), printf (<stdio.h>) y size_t (<stddef.h>).
⚠️ Casos límite¶
Algunos compiladores (GCC 14+) convierten la declaración implícita en error por defecto; en ese caso el cast no ayuda y el código no compila.
El cast de
callocyreallocsin<stdlib.h>reproduce el mismo riesgo.Incluir
<stdlib.h>no justifica mantener el cast redundante (ver0x300Ah).
Errores típicos al compilar o ejecutar¶
$ gcc -std=c11 -pedantic-errors programa.c
programa.c: In function 'main':
programa.c:3:14: error: implicit declaration of function 'malloc'
[-Wimplicit-function-declaration]
# En compilador permisivo:
programa.c:3:14: warning: implicit declaration of function 'malloc'
$ ./programa
Segmentation fault (core dumped)Checklist de verificación¶
¿Está
#include <stdlib.h>cuando usomalloc,calloc,reallocofree?¿Quité el cast
(tipo *)delante demalloc?¿El compilador no emite
-Wimplicit-function-declaration?¿El programa compila con
-std=c11 -pedantic-errors?
Reglas relacionadas¶
0x300Ah: Utilizá cast explícito al convertir tipos de punteros — cast solo cuando la conversión lo requiere.
0x500Bh: Inclusión obligatoria de cabeceras estándar para funciones de la biblioteca C — inclusión obligatoria de cabeceras estándar.
0x5014h: Inclusión explícita obligatoria de cabeceras para funciones de biblioteca estándar — no depender de declaraciones implícitas.
0x300Ah: Utilizá cast explícito al convertir tipos de punteros — el cast sin el include faltante.
Antipatrón: Casteo forzado de tipos numéricos o literales enteros a punteros¶
Síntoma en el código del estudiante¶
Se fabrica un puntero a partir de un entero literal:
int *p = (int *)0x1000;
*p = 42;El número pretende ser una dirección de memoria “conocida”, tomada de un ejemplo, de una dirección de hardware o de la imaginación.
Diagnóstico¶
Mecanismo del defecto¶
Un entero y un puntero pertenecen a dominios distintos. Convertir un entero a puntero es posible con cast, pero el estándar lo declara implementation-defined: cada plataforma decide qué significa, y el resultado puede no ser una dirección válida ni conservar el valor numérico.
El problema se materializa al desreferenciar. En un sistema con memoria virtual,
la dirección 0x1000 (4096) rara vez está mapeada para el proceso. El acceso
genera una falla de página y SIGSEGV. Elegir “de memoria” 0x1000 es
especialmente desafortunado: cae en la primera página, deliberadamente no
mapeada para detectar desreferencias nulas.
Escribir en una dirección fija solo tiene sentido en código de muy bajo nivel —un arranque de kernel, un registro mapeado en memoria— con documentación y mapeo explícito. Fuera de ese contexto es un error de portabilidad y una caída segura.
Consecuencia observable¶
SIGSEGVal desreferenciar la dirección inventada.El código deja de compilar o cambia de significado en otra plataforma.
Si la dirección coincide con memoria válida por casualidad, corrompe datos ajenos.
El compilador puede advertir con
-Wint-to-pointer-castsegún la constancia.
Fundamento en el estándar C11¶
C11 §6.3.2.3p5: la conversión de entero a puntero es implementation-defined; el resultado puede no estar alineado ni ser utilizable.
C11 §6.5.3.2p4: desreferenciar un puntero que no apunta a un objeto es comportamiento indefinido.
C11 §6.3.2.3p3: la única constante entera que se convierte en puntero nulo es
0;NULLes la forma canónica y0x1000no es un puntero nulo.La regla 0x300Ah regula las conversiones entre punteros, no habilita inventar direcciones.
Corrección idiomática¶
❌ Código con el antipatrón¶
int *p = (int *)0x1000;
*p = 42;✅ Código refactorizado — obtener la dirección de un objeto real¶
int valor = 0;
int *p = &valor;
*p = 42;✅ Memoria dinámica¶
int *p = malloc(sizeof(*p));
if (p == NULL) {
return NULL;
}
*p = 42;
free(p);
p = NULL;✅ Puntero nulo cuando corresponde¶
int *p = NULL; /* no (int *)0 */NULL expresa “sin objeto”; un literal como 0x1000 expresa una dirección
concreta que probablemente no exista.
⚠️ Casos límite¶
(void *)0es una constante de puntero nulo válida, pero en C la cátedra prefiereNULL(regla 0x3008h).En entornos embebidos con registros mapeados,
volatiley una dirección fija pueden ser legítimos; requieren justificación y quedan fuera del alcance de la materia.Si de verdad se necesita una dirección en un entero, el tipo correcto es
uintptr_t(<stdint.h>), no unint.
Errores típicos al compilar o ejecutar¶
$ gcc -Wall -Wextra -std=c11 programa.c
programa.c:1:9: warning: cast to pointer from integer of different size
[-Wint-to-pointer-cast]
1 | int *p = (int *)0x1000;
$ ./programa
Segmentation fault (core dumped)Checklist de verificación¶
¿Todo puntero proviene de
malloc/calloc/realloco de&objeto?¿Eliminé los literales enteros casteados a puntero?
¿Uso
NULLy no(tipo *)0para indicar ausencia de objeto?¿Si necesito una dirección en un entero uso
uintptr_t?
Reglas relacionadas¶
0x300Ah: Utilizá cast explícito al convertir tipos de punteros — conversiones de punteros explícitas y legítimas.
0x3008h: Los punteros nulos deben ser inicializados y comparados con NULL, no con 0 —
NULLpara punteros, no literales.0x3001h: Siempre verificá la asignación exitosa de memoria dinámica — verificar el retorno de la reserva.
0x3001h: Siempre verificá la asignación exitosa de memoria dinámica — la conversión inversa, igualmente peligrosa.