Je viens de faire un bond en apprenant que en C ANSI, il serait “deprecated” et même dangereux de faire un cast explicite sur la valeur de retour d’un malloc. Alors qu’au contraire, c’est recommandé en C pre-ANSI et en C++ (faut vraiment avoir envie d’utiliser malloc en C++, mais bon).
Quelqu’un peut m’éclairer sur le pourquoi du comment ? J’ai vraiment du mal à comprendre, même en relisant bien soigneusement l’explication (pourtant de source sérieuse, c’est dans l’errata de “The C programming language” de K&R) :
The remark about casting the return value of malloc (“the proper method is to declare … then explicitly coerce”) needs to be rewritten. The example is correct and works, but the advice is debatable in the context of the 1988-1989 ANSI/ISO standards. It’s not necessary (given that coercion of void * to ALMOSTANYTYPE * is automatic), and possibly harmful if malloc, or a proxy for it, fails to be declared as returning void *. The explicit cast can cover up an unintended error. On the other hand, pre-ANSI, the cast was necessary, and it is in C++ also.
La source est ici : http://cm.bell-labs.com/cm/cs/cbook/2ediffs.html
Je suis globalement relativement d’accords avec LA THEORIE, en ce qui concerne la pratique, c’est
given that coercion of void * to ALMOSTANYTYPE * is automatic
qui me chagrine : la plus part des compilos vont couiner si tu fait pas un bon vieux cast des familles… donc en attendant qu’ils aient une autre idee : castont !
Ce qui me perturbe c’est le fait que ça puisse avoir des effets pervers de faire un cast en C ANSI, en considérant qu’on a un compilo qui implémente le standard à 100%. Je suis conscient que ce soit une question théorique…
En fait, ce qui m’a fait aussi bondir, c’est que je tiens cette information d’un ami qui est à l’université et qui m’a dit que son prof de C retire des points aux étudiants qui osent faire un cast sur un malloc. J’ai eu ce prof là aussi, mais pas dans cette branche heureusement. Ouf.
Idem, les compilos couinent chez moi aussi si je caste pas. Et pour le coup de « ça peut cacher une erreur », rooooh, de toute façon en C tu peux faire port’nawak si tu veux alors… Surtout qu’un couillon qui redéfinit malloc sans qu’il retourne void * mérite la bastonnade publique Si tu veux faire ça, tu fais ta fonction a toi « MonAllocQuilEstJoli » et voila. Non mais.
Pareil, jamais eu de problème avec l’absense de cast pour un malloc.
Si le compilo rale c’est soit qu’il suit pas la norme, ou que stdlib.h n’a pas été inclus et donc “implicit declaration of function `malloc’” ce qui nous donne un malloc qui renvoi un int (et c’est pour ca que ca fait un peu raller le compilateur quand on assigne un int à un pointeur).
C’est peut etre parce que vous bossez grosso modo sur la meme machine/archi, en utilisant le meme toolchain (le meme ou base sur le meme), parce que je pourait lister au moins 3/4 compilos qui couinent des que tu essayes de caster un malloc sur autre chose qu’un base-type (int, char void et compagnies).
bon c’est vrai que moi c’est surtout gcc, mais j’ai utilisé plein de cross-compiler pour des archis différentes car je fais pas mal de systèmes embarqués, mais jamais eu de couinement …
Bon, c’est vrai que souvent les toolchain sont basés sur gcc !!!
Euh, les warnings dépendent assez peu de l’archi en fait, mais beaucoup plus du compilo hein GCC il te fera les memes warning (sauf ceux spécifiques a la plateforme) sur toutes les archis a priori…
Ouais c’est plutot ça en fait… de toute façon GCC a une grosse base commune sur toutes les plateformes, donc quand on me dit “sisi j’utilise pleins de compilos : GCC sous linux, GCC sous windows, GCC sous BeOS, GCC sous FreeBSD”, ben ça me fait sourire
Merci pour les explications… Et tant qu’on y est, dans le même ordre d’idées, vous saviez que l’usage de “NULL” est déconseillé en C++ ? Faut utiliser 0 à la place, car NULL est une macro qui fait un cast explicite de 0 en void*, et assiger un void* à un pointeur d’un type différent c’est à éviter…
Cependant en C, pas de problème… Le C est décidément parfois bien étrange. Et vive le C++, yop feed the troll
Je ne vois pas bien pourquoi ça serait moins “risqué” de faire :
CMyClass * ptr = new CMyClass() ;
if( ptr == (CMyClass *)0 )
gnagna
plutôt que de faire :
if( ptr == NULL )
gnagna
ou encore :
if( ptr == 0 )
gnagna
sachant que dans le dernier cas le compilo va couiner car il va comparer un pointeur avec une valuer entière. Pour ma part, j’utilise le second cas et je ne me fais pas chier à typer la valeur 0 (premier cas).
[quote]Merci pour les explications… Et tant qu’on y est, dans le même ordre d’idées, vous saviez que l’usage de “NULL” est déconseillé en C++ ? Faut utiliser 0 à la place, car NULL est une macro qui fait un cast explicite de 0 en void*, et assiger un void* à un pointeur d’un type différent c’est à éviter…
Cependant en C, pas de problème… Le C est décidément parfois bien étrange. Et vive le C++, yop feed the troll [/quote]Ouais, mais utiliser un 0 en dur, spa propre… Autant redefinir la macro NULL en 0 (ce que je fais le plus souvent). #define NULL 0
Sinon, je conchies tout cast implicite, ca tue le typage fort et amène le Dev a faire des conneries.
Note : si ma mémoire est bonne, un malloc non casté sous VS en Warning niveau 4 sort un warning (comme toute convertion implicite).
ouais moi aussi, les cast implicites, je peux pas, ça me fait dresser les cheveux à chaque fois, j’ai tellement l’impression de perdre le contrôle de mon programme et de laisser le choix à gcc, et là justement avec les cast implicites tu peux avoir de grosses surprises pour porter ton code d’une archi à l’autre !!!