Les pointeurs de fonctions

Prototype


La première règle est :  ne les utilisez pas si vous n’avez pas à le faire\footnote{On lira avec intérêt le fichier /usr/include/ctype.h}. Il a pu être observé qu’à peu près chaque macro démontre un défaut dans la programmation. Puisqu’elles réorganisent le texte d’un programme avant que le compilateur ne les voit, les macros sont un problème majeur pour la plupart des outils de développement (débogueurs, profileurs\ldots).

Rappel

Une directive (macro-instruction\footnote{Mammeri M. {\it programmation} {\sc école centrale de paris} {\tiny 1997-1998} p. 112}) de prétraitement de la forme :
#define identificateur chaine-symbole
provoque le remplacement par le préprocesseur de toutes les instances suivantes de l’identificateur avec la séquence de symboles donnée. Les espaces entourant la séquence de symboles de remplacement sont annulés. Par exemple :
#define COTE 8
char jeu[COTE][COTE] ;
devient après le passage du précompilateur :
char jeu [8] [8] ;

Opérateur #

Si une occurrence d’un paramètre dans une séquence de symboles de remplacement est immédiatement précédée par un symbole #, le paramètre et l’opérateur # seront remplacés dans le développement par un littéral chaîne contenant l’orthographe de l’argument correspondant. Un caractère \ est inséré dans un littéral chaîne avant chaque occurrence d’un \ ou d’un " à l’intérieur d’une (ou délimitant) une constante caractère ou un littéral chaîne dans l’argument.
#define path(logid,cmd) "/users/" #logid "/bin/" #cmd
#define jjd dhenin
à l’appel
char * outil = path(jjd, listlp) ;
sera interprété :
char * outil = "/users/" "jjd" "/bin/" "listlp" ;
qui sera ensuite concaténé pour devenir :
char * outil = "/users/jjd/bin/listlp" ;

Opérateur ##

Si un opérateur ## apparaît entre deux symboles dans une séquence de symboles de remplacement, et si l’un ou l’autre des symboles est un paramètre, il est tout d’abord remplacé, puis l’opérateur ## et tous les espaces l’entourant sont ensuite supprimés. L’effet de l’opérateur ## est donc une concaténation. Par exemple dans la création du TDA liste (Liste.h et Liste.tda)
#define nom(a,b) a##b
#define liste(type_objet)            \
void nom (type_objet, liste_premier) \
(nom(type_objet, liste) l)           \
{                                    \
(*Liste.premier) (l->rep) ;          \
}

liste(Entier) ;
produira :
void Entierliste_premier(Entierliste l)
{
(*Liste.premier) (l->rep) ;
}
Mais toute macro utilisée comme un des symboles adjacents à ## n’est pas expansée, à l’inverse du résultat de la concaténation. donne rafiscotche et non pas Bvalise
#define concat(a) a##valise
#define mot B
#define motvalise rafiscotche

contate(mot)
main ()
{
int a = 1 ;
int B = 2 ;
int Bvalise = 3 ;
int rafiscotche = 4 ;

printf ("%d\n", concat(mot)) ;
}
Les pointeurs de fonctions