Eu coloquei no elenco simplesmente para mostrar a desaprovação do buraco feio no sistema de tipos, que permite que códigos como o seguinte trecho sejam compilados sem diagnóstico, mesmo que nenhum elenco seja usado para provocar uma conversão ruim:
double d;
void *p = &d;
int *q = p;
Eu gostaria que isso não existisse (e não existe em C ++) e, por isso, fiz a transmissão. Representa meu gosto e minha política de programação. Não estou apenas lançando um ponteiro, mas efetivamente, votando e expulsando demônios da estupidez . Se eu realmente não posso expulsar a estupidez , pelo menos deixe-me expressar o desejo de fazê-lo com um gesto de protesto.
De fato, uma boa prática é agrupar malloc(e amigos) com funções que retornam unsigned char *e basicamente nunca usar void *em seu código. Se você precisar de um ponteiro genérico para qualquer objeto, use a char *ou unsigned char *e tenha projeções nas duas direções. O único relaxamento que pode ser tolerado, talvez, é usar funções como memsete memcpysem elencos.
No tópico fundição e compatibilidade com C ++, se você escrever seu código para que ele seja compilado tanto em C quanto em C ++ (nesse caso, você precisará converter o valor de retorno mallocao atribuí-lo a algo diferente de void *), poderá fazer uma ajuda muito útil coisa para você: você pode usar macros para conversão que convertem para conversões no estilo C ++ ao compilar como C ++, mas reduzem para uma conversão C ao compilar 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
Se você aderir a essas macros, uma simples greppesquisa na sua base de códigos por esses identificadores mostrará onde estão todas as suas transmissões, para que você possa verificar se alguma delas está incorreta.
A partir de agora, se você compilar regularmente o código com C ++, ele aplicará o uso de uma conversão apropriada. Por exemplo, se você usar strip_qualapenas para remover um constou volatile, mas o programa mudar de tal maneira que uma conversão de tipo esteja envolvida, você receberá um diagnóstico e precisará usar uma combinação de conversões para obter a conversão desejada.
Para ajudá-lo a aderir a essas macros, o compilador GNU C ++ (não C!) Possui um recurso bonito: um diagnóstico opcional produzido para todas as ocorrências de conversões no estilo C.
-Construção no estiloold (apenas C ++ e Objective-C ++)
Avisar se uma conversão de estilo antigo (estilo C) para um tipo não nulo é usada
dentro de um programa C ++. O novo estilo lança (dynamic_cast,
static_cast, reinterpret_cast e const_cast) são menos vulneráveis
para efeitos não intencionais e muito mais fáceis de pesquisar.
Se o seu código C for compilado como C ++, você poderá usar esta -Wold-style-castopção para descobrir todas as ocorrências da (type)sintaxe de conversão que podem surgir no código e acompanhar esses diagnósticos, substituindo-o por uma escolha apropriada dentre as macros acima (ou um combinação, se necessário).
Esse tratamento de conversões é a maior justificativa técnica autônoma para trabalhar em um "C limpo": o dialeto C e C ++ combinado, que por sua vez tecnicamente justifica lançar o valor de retorno de malloc.