Le prototype de la fonction C malloc est : void *malloc(size_t size); Il existe deux « écoles » concernant l'assignation du pointeur retourné par malloc. Celle qui prône la conversion explicite (cast) du pointeur retourné ; et celle qui prône sa conversion implicite. Soit :
int *p; p = (int*)malloc(sizeof(int)); /* école explicite */ p = malloc(sizeof *p); /* école implicite */ Les deux solutions sont valides en C car les conversions d'un pointeur de donnée de et vers void* sont implicites (c'est un peu le but de l'existence de void*). Une faiblesse de la conversion explicite est de pouvoir masquer l'oubli de #include <stdlib.h>. En effet, en cas d'oubli, le compilateur construit une déclaration implicite de malloc avec int pour type de retour (le type par défaut de C). Et dans notre exemple, la conversion explicite convertirait silencieusement en int* ce int implicitement déclaré. Si int et int* ont par chance la même taille, alors on ne se rendra probablement compte de rien. Mais s'ils n'ont pas la même taille, alors on obtiendra probablement un crash à l'exécution. Si l'on s'était reposé sur une conversion implicite, le compilateur aurait refusé la conversion implicite de int en pointeur et le bug serait apparu à la compilation. Notons toutefois que les compilateurs modernes peuvent lancer un avertissement en cas de déclaration implicite de fonction, et qu'il est unanimement déconseillé de reposer sur la déclaration implicite des fonctions (c'est même impossible en C++). Une faiblesse de la conversion implicite est de pouvoir masquer une désynchronisation entre le type de pointeur et la taille de l'allocation. Si l'on écrit : p = malloc(sizeof(int)); et que la déclaration de p est changée (par exemple en long *p;), alors le compilateur n'émettra aucun avertissement. Pour éviter cette désynchronisation, on peut écrire : p = malloc(sizeof *p); Mais ce genre de déclaration perd en lisibilité dans les assignations plus complexes : *node->element.ref = malloc(sizeof **node->element.ref); et peut aussi assez facilement finir silencieusement erroné suite à un copier/coller. Remarques : En C++, la conversion avec void* doit être explicite, mais le problème ne se pose guère car on n'utilise en principe pas malloc en C++. En vieux C non standard, malloc retournait souvent un char* (void n'existait pas à cette époque). Les vieux compilateurs convertissaient implicitement un peu tout en n'importe quoi. Mais si l'on utilisait un compilateur plus moderne (ne convertissant pas implicitement un char* en int*) avec une vieille bibliothèque C où malloc retournait un char*, alors il fallait ajouter une conversion explicite. -- Marc Mongenet Creator of the Web 2 Markup Language http://w2ml.com _______________________________________________ gull mailing list [email protected] https://secure.alphanet.ch/cgi-bin/mailman/listinfo/gull
