J'ai mis le casting simplement pour montrer la désapprobation du trou laid dans le système de type, ce qui permet à du code tel que l'extrait suivant de compiler sans diagnostic, même si aucune conversion n'est utilisée pour provoquer la mauvaise conversion:
double d;
void *p = &d;
int *q = p;
Je souhaite que cela n'existe pas (et ce n'est pas le cas en C ++) et j'ai donc casté. Il représente mon goût et ma politique de programmation. Non seulement je jette un pointeur, mais effectivement, je vote et je chasse les démons de la stupidité . Si je ne peux pas vraiment chasser la bêtise , au moins laissez - moi exprimer le souhait de le faire avec un geste de protestation.
En fait, une bonne pratique consiste à encapsuler malloc
(et à vos amis) les fonctions qui reviennent unsigned char *
, et à ne jamais utiliser void *
dans votre code. Si vous avez besoin d'un pointeur générique vers n'importe quel objet, utilisez un char *
ou unsigned char *
et avez des transtypages dans les deux directions. La seule relaxation à laquelle on peut s'adonner, peut-être, est d'utiliser des fonctions comme memset
et memcpy
sans transtypage.
Sur le sujet de la conversion et de la compatibilité C ++, si vous écrivez votre code de sorte qu'il se compile à la fois en C et C ++ (auquel cas vous devez convertir la valeur de retour de malloc
lors de son affectation à autre chose que void *
), vous pouvez faire une très utile chose pour vous: vous pouvez utiliser des macros pour la conversion qui se traduisent par des transtypages de style C ++ lors de la compilation en C ++, mais réduisent à une conversion C lors de la compilation en 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 vous adhérez à ces macros, une simple grep
recherche dans votre base de code pour ces identifiants vous montrera où se trouvent toutes vos conversions, afin que vous puissiez vérifier si certaines d'entre elles sont incorrectes.
Ensuite, si vous compilez régulièrement le code avec C ++, cela imposera l'utilisation d'une conversion appropriée. Par exemple, si vous utilisez strip_qual
simplement pour supprimer un const
ou volatile
, mais que le programme change de telle manière qu'une conversion de type est maintenant impliquée, vous obtiendrez un diagnostic et vous devrez utiliser une combinaison de transtypages pour obtenir la conversion souhaitée.
Pour vous aider à adhérer à ces macros, le compilateur GNU C ++ (pas C!) A une belle fonctionnalité: un diagnostic optionnel qui est produit pour toutes les occurrences de transtypages de style C.
-Wold-style-cast (C ++ et Objective-C ++ uniquement)
Avertir si une conversion à l'ancienne (style C) vers un type non nul est utilisée
au sein d'un programme C ++. Les transtypages de nouveau style (dynamic_cast,
static_cast, reinterpret_cast et const_cast) sont moins vulnérables
aux effets inattendus et beaucoup plus facile à rechercher.
Si votre code C se compile en C ++, vous pouvez utiliser cette -Wold-style-cast
option pour trouver toutes les occurrences de la (type)
syntaxe de transtypage qui peuvent se glisser dans le code, et poursuivre ces diagnostics en le remplaçant par un choix approprié parmi les macros ci-dessus (ou un combinaison, si nécessaire).
Ce traitement des conversions est la plus grande justification technique autonome pour travailler dans un "Clean C": le dialecte combiné C et C ++, qui à son tour justifie techniquement la conversion de la valeur de retour de malloc
.