Puse el elenco simplemente para mostrar la desaprobación del agujero feo en el sistema de tipos, que permite que el código como el siguiente fragmento se compile sin diagnóstico, a pesar de que no se utilizan moldes para provocar la conversión incorrecta:
double d;
void *p = &d;
int *q = p;
Desearía que no existiera (y no existe en C ++) y, por lo tanto, lancé. Representa mi gusto y mi política de programación. No solo estoy lanzando un puntero, sino efectivamente, votando y expulsando demonios de estupidez . Si no puedo realmente echar fuera la estupidez , a continuación, al menos permítanme expresar el deseo de hacerlo con un gesto de protesta.
De hecho, una buena práctica es envolver malloc
(y amigos) con funciones que regresan unsigned char *
, y básicamente nunca usarlas void *
en su código. Si necesita un puntero genérico a cualquier objeto, use un char *
o unsigned char *
, y tenga conversiones en ambas direcciones. La única relajación que puede permitirse, tal vez, es usar funciones como memset
y memcpy
sin yesos.
Sobre el tema de la compatibilidad de conversión y C ++, si escribe su código para que se compile como C y C ++ (en cuyo caso debe emitir el valor de retorno malloc
al asignarlo a otra cosa que no sea void *
), puede hacer algo muy útil cosa para usted: puede usar macros para la conversión que se traducen en conversiones de estilo C ++ cuando se compila como C ++, pero se reducen a una conversión C cuando se compila como C:
/* In a header somewhere */
#ifdef __cplusplus
#define strip_qual(TYPE, EXPR) (const_cast<TYPE>(EXPR))
#define convert(TYPE, EXPR) (static_cast<TYPE>(EXPR))
#define coerce(TYPE, EXPR) (reinterpret_cast<TYPE>(EXPR))
#else
#define strip_qual(TYPE, EXPR) ((TYPE) (EXPR))
#define convert(TYPE, EXPR) ((TYPE) (EXPR))
#define coerce(TYPE, EXPR) ((TYPE) (EXPR))
#endif
Si se adhiere a estas macros, una simple grep
búsqueda en su base de código para estos identificadores le mostrará dónde están todos sus moldes, para que pueda revisar si alguno de ellos es incorrecto.
Luego, en el futuro, si compila regularmente el código con C ++, impondrá el uso de un reparto apropiado. Por ejemplo, si usa strip_qual
solo para eliminar a const
o volatile
, pero el programa cambia de tal manera que ahora se trata de una conversión de tipo, obtendrá un diagnóstico y tendrá que usar una combinación de conversiones para obtener la conversión deseada.
Para ayudarlo a adherirse a estas macros, el compilador GNU C ++ (¡no C!) Tiene una hermosa característica: un diagnóstico opcional que se produce para todas las apariciones de modelos de estilo C.
-Wold-style-cast (solo C ++ y Objective-C ++)
Avisar si se utiliza una conversión de estilo antiguo (estilo C) a un tipo no vacío
dentro de un programa C ++. Los lanzamientos de estilo nuevo (dynamic_cast,
static_cast, reinterpret_cast y const_cast) son menos vulnerables
a efectos no deseados y mucho más fácil de buscar.
Si su código C se compila como C ++, puede usar esta -Wold-style-cast
opción para averiguar todas las apariciones de la (type)
sintaxis de conversión que pueden aparecer en el código, y hacer un seguimiento de estos diagnósticos reemplazándolo con una elección adecuada entre las macros anteriores (o un combinación, si es necesario).
Este tratamiento de conversiones es la justificación técnica independiente más grande para trabajar en una "C limpia": el dialecto combinado de C y C ++, que a su vez técnicamente justifica emitir el valor de retorno de malloc
.