Bonjour, j'écris cette modeste présentation d'une subtilité du langage C suite à la lecture de l'article "Who maintains dpkg?" de LWN.net (Linux Weekly News) : http://lwn.net/Articles/273714/.
Note : cet article est réservé pour encore quelques jours aux abonnés de LWN.net. Je profite d'un abonnement offert par le GULL. Un article de 2004, "NULL v. zero", aborde aussi le sujet des pointeurs nuls en C et est publiquement accessible : http://lwn.net/Articles/93574/. Dans le débat enflammé autour de la maintenance de dpkg ("Re: dpkg semi-hijack - an announcement (also, triggers)" http://article.gmane.org/gmane.linux.debian.devel.general/125926) il y a entre autres une dispute technique autour du diff suivant : http://git.debian.org/?p=dpkg/dpkg.git;a=commit;h=4e5846ccd3dcc33504aba8ef35a8962bccfd562e Use NULL instead of '(char *)0'. On y trouve des modifications ressemblant à cela : - execlp(TAR,"tar",buffer,"-",(char*)0); + execlp(TAR, "tar", buffer, "-", NULL); Que peut-on en dire ? La fonction execlp a le prototype suivant : int execlp(const char *file, const char *arg, ...); Il s'agit d'une fonction à nombre variable de paramètres. Les paramètres optionnels sont traités comme étant de type const char* d'après mon man sur Linux. D'après le standard C, la macro NULL doit être définie en une "null pointer constant" et "integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant". Bref, il est généralement admis que NULL peut être définie en 0 ou en ((void*)0). Or sizeof 0 peut être différent de sizeof((void*)0). Sur Motorola 68000 et certains modes de fonctionnement des i386, on pouvait notamment avoir sizeof 0==2 et sizeof((void*)0)==4 (entiers 16 bits, pointeurs 32 bits). Avec la transition actuelle au 64 bits, on peut avoir sizeof 0==4 et sizeof((void*)0)==8. Bref, en écrivant NULL au lieu de (char*)0, on risque de passer une donnée plus petite qu'attendue à la fonction, et causer un crash. Cela dit, on peut argumenter qu'aucune bibliothèque C serait assez perverse pour définir NULL en 0 alors que sizeof 0!=sizeof((void*)0). Cependant, même avec NULL définit en ((void*)0), il reste la question de la compatibilité avec ((char*)0). En effet, le standard C n'oblige pas tous les pointeurs à avoir la même taille. Cependant, le standard C prend la peine de préciser que les pointeurs sur void et les pointeur sur un type caractère doivent être interchangeables. Ouf. Pour conclure, ma page man execlp en anglais précise : The list of arguments must be terminated by a NULL pointer, and, since these are variadic functions, this pointer must be cast (char *) NULL. Dans la documentation de l'Open Group on trouve (char*)0 : http://www.opengroup.org/onlinepubs/007908799/xsh/exec.html Cette subtilité semble avoir échappé au traducteur français (à moins que la traduction soit basée sur une ancienne version anglaise incomplète) : Le tableau de pointeur doit se terminer par un pointeur NULL. Marc Mongenet _______________________________________________ gull mailing list [email protected] https://secure.alphanet.ch/cgi-bin/mailman/listinfo/gull
