utiliza que punteros puntero ejemplos como apuntadores c pointers casting

que - En C, ¿por qué algunas personas lanzan el puntero antes de liberarlo?



puntero malloc (6)

Estoy trabajando en una base de código antigua y casi todas las invocaciones de free () usan un reparto en su argumento. Por ejemplo,

free((float *)velocity); free((float *)acceleration); free((char *)label);

donde cada puntero es del tipo correspondiente (y coincidente). No veo ningún punto en hacer esto en absoluto. Es un código muy antiguo, así que me pregunto si es algo de K&R. Si es así, en realidad deseo admitir los compiladores antiguos que pueden haber requerido esto, por lo que no quiero eliminarlos.

¿Hay alguna razón técnica para usar estos moldes? Ni siquiera veo una gran razón pragmática para usarlos. ¿Cuál es el punto de recordarnos el tipo de datos justo antes de liberarlo?

EDITAR: Esta pregunta no es un duplicado de la otra pregunta. La otra pregunta es un caso especial de esta pregunta, que creo que es obvio si los votantes cercanos leen todas las respuestas.

Colofón: le doy a la "respuesta constante" la marca de verificación porque es una verdadera razón genuina por la que esto podría ser necesario; sin embargo, la respuesta sobre que es una costumbre C anterior a ANSI (al menos entre algunos programadores) parece ser la razón por la que se usó en mi caso. Un montón de buenos puntos por muchas personas aquí. Gracias por sus aportaciones.


Aquí hay otra hipótesis alternativa.

Se nos dice que el programa fue escrito antes de C89, lo que significa que no puede estar trabajando en algún tipo de desajuste con el prototipo de free , porque no solo no había tal cosa ni void * antes de C89, había No existe un prototipo de función anterior a C89. stdlib.h sí fue un invento del comité. Si los encabezados del sistema se hubieran molestado en declarar free , lo habrían hecho así:

extern free(); /* no `void` return type either! */

Ahora, el punto clave aquí es que la ausencia de prototipos de funciones significa que el compilador no realizó ninguna comprobación de tipo de argumento . Aplicó las promociones de argumento por defecto (las mismas que todavía se aplican a las llamadas a funciones variadas) y eso fue todo. La responsabilidad de hacer que los argumentos en cada sitio de llamadas se alineen con las expectativas del destinatario recae completamente en el programador.

Sin embargo, esto todavía no significa que era necesario lanzar el argumento de forma free en la mayoría de los compiladores de K&R. Una función como

free_stuff(a, b, c) float *a; char *b; int *c; { free(a); free(b); free(c); }

debería haber sido compilado correctamente. Así que creo que lo que tenemos aquí es un programa escrito para hacer frente a un compilador con errores para un entorno inusual: por ejemplo, un entorno donde sizeof(float *) > sizeof(int) y el compilador no usarían las llamadas apropiadas convención para punteros a menos que los lance en el punto de la llamada.

No conozco ningún entorno de ese tipo, pero eso no significa que no haya ninguno. Los candidatos más probables que vienen a la mente son los compiladores "C minúsculos" reducidos para micros de 8 y 16 bits a principios de la década de 1980. Tampoco me sorprendería saber que Crays temprano tuvo problemas como este.


Aquí hay un ejemplo en el que free fallaría sin un elenco:

volatile int* p = (volatile int*)malloc(5 * sizeof(int)); free(p); // fail: warning C4090: ''function'' : different ''volatile'' qualifiers free((int*)p); // success :) free((void*)p); // success :)

En C puede obtener una advertencia (obtuvo una en VS2012). En C ++ obtendrá un error.

Dejando a un lado casos raros, el casting simplemente hincha el código ...

Editar: lancé para void* no int* para demostrar la falla. Funcionará igual que int* se convertirá a void* implícitamente. Código int* agregado.


El C preestándar no tenía void* sino solo char* , por lo que tenía que emitir todos los parámetros pasados. Si se encuentra con el antiguo código C, por lo tanto, puede encontrar dichos modelos.

Pregunta similar con referencias .

Cuando se lanzó el primer estándar C, los prototipos para malloc y free cambiaron de tener char* al void* que todavía tienen hoy.

Y, por supuesto, en el estándar C, tales modelos son superfluos y solo dañan la legibilidad.


Razón anterior: 1. Al usar free((sometype*) ptr) , el código es explícito sobre el tipo de puntero que debe considerarse como parte de la llamada free() . El reparto explícito es útil cuando free() se reemplaza con un (hágalo usted mismo) DIY_free() .

#define free(ptr) DIY_free(ptr, sizeof (*ptr))

Un DIY_free() era (es) una forma, especialmente en modo de depuración, de hacer un análisis en tiempo de ejecución del puntero que se está liberando. Esto a menudo se combina con un DIY_malloc() para agregar sentencias, recuentos de uso de memoria global, etc. Mi grupo usó esta técnica durante años antes de que aparecieran herramientas más modernas. Obligó a que el elemento que se liberara fuera lanzado al tipo que se asignó originalmente.

  1. Dadas las muchas horas dedicadas a rastrear problemas de memoria, etc., pequeños trucos como lanzar el tipo free''d ayudarían a buscar y reducir la depuración.

Moderno: evitar advertencias const y volatile según lo abordado por Manos Nikolaidis @ y @egur . Pensé que notaría los efectos de los 3 calificadores : const , volatile y restrict .

[editar] Se agregó char * restrict *rp2 por @R .. comentario

void free_test(const char *cp, volatile char *vp, char * restrict rp, char * restrict *rp2) { free(cp); // warning free(vp); // warning free(rp); // OK free(rp2); // warning } int main(void) { free_test(0,0,0,0); return 0; }


Se puede requerir el envío para resolver las advertencias del compilador si los punteros son const . Aquí hay un ejemplo de código que causa una advertencia sin lanzar el argumento de free:

const float* velocity = malloc(2*sizeof(float)); free(velocity);

Y el compilador (gcc 4.8.3) dice:

main.c: In function ‘main’: main.c:9:5: warning: passing argument 1 of ‘free’ discards ‘const’ qualifier from pointer target type [enabled by default] free(velocity); ^ In file included from main.c:2:0: /usr/include/stdlib.h:482:13: note: expected ‘void *’ but argument is of type ‘const float *’ extern void free (void *__ptr) __THROW;

Si usa free((float*) velocity); El compilador deja de quejarse.