C'est bien sizeof(&*(x)) : si x est un tableau (par exemple int[42]), *x sera un int, et &*x sera un int*. Donc sizeof(&*x)=4 sera différent de sizeof(x)=42*2, donc on est sûr que x n'est pas un simple pointeur et que sizeof(x) est bien le nombre d'éléments du tableau.
sizeof(*&x), lui, est tjs égal à sizeof(x) que x soit un tableau ou non, et en plus n'est pas toujours défini (enfin pour un tableau, il devrait tjs l'être, remarque...)
Zephyr>
vi c ultra-crade, mais bon t'es pas censé la voir la ligne en question, et puis tu es qd même *certain* de ne pas te planter, ça pourrait être utile

(enfin, perso j'utiliserais pas ça pour un programme portable, au cas où sur une plateforme exotique on tomberait sur un tableau qui fait exactement la taille d'un pointeur : en revanche rien ne t'empêche d'utiliser cette définition quand toi tu compiles, pour t'assurer que les numberof() sont bien ok, et d'utiliser la définition de PpHd pour les versions publiques...)
Et puis il y a un autre pb, c'est que les assert() sont dynamiques et pas statiques : tu peux t'en sortir en appelant une fonction définie nulle part à la place de assert() (en priant pour que le compilo supprime l'appel de fonction s'il ne peut pas être atteint, sinon la compilation échouerait => pas complètement portable, mais bon si c juste pour toi c pas un pb), ou en greppant la chaîne en question dans l'exécutable (mais bon, ça c encore moins portable), mais t'as raison, c bien dégueulasse et ça apporte pas gd chose par rapport à #define ARRAY_SIZE

Enfin ça aurait été sympa si le C avait prévu un numberof() ou au moins un truc qui balance une erreur si l'argument n'est pas un tableau, parce que sizeof() est très casse-gueule de ce point de vue-là...