Je pense que je souffre peut-être de la maladie redoutée des “programmeurs accidentels”, du moins en ce qui concerne les libellés de caractères et les indicateurs de fonction. J’ai donc expérimenté toutes sortes de combinaisons impliquant ces parsings pour parsingr les résultats en fonction de tous les résultats obtenus.
Mais comme je continuais à essayer différentes combinaisons, au lieu d’parsingr les résultats, je suis maintenant perdu dans le processus.
J’espère que vous m’aiderez à comprendre ce gâchis.
Premier exemple de code
typedef void (print)(void); void do_something (void) { printf("Hello World\n"); } print *pr; pr = &do_something; pr(); // Hello World
Deuxième exemple de code
typedef void (print)(void); void do_something (void) { printf("Hello World\n"); } print *pr; pr = do_something; pr(); // Hello World
Comment fonctionnent les deux exemples de code ci-dessus, c’est comme si ‘&’ n’avait aucun effet sur le nom de la fonction
troisième exemple de code
typedef void (print)(void); void do_something (void) { printf("Hello World\n"); } print pr; pr = do_something; // comstack error pr = &do_something; // comstack error pr();
J’espérais que l’un des mandats ci-dessus fonctionnerait ici, mais bon sang! Je ne comprends vraiment pas les indicateurs de fonction (et peut-être aussi typedef).
L’adresse d’un nom de fonction et le nom de fonction en clair signifient la même chose, donc &
n’a pas d’effet sur le nom de la fonction.
De même, lors de l’utilisation de pointeurs de fonction, la déréférencement multiple n’est pas un problème:
#include typedef void print(void); static void dosomething(void) { printf("Hello World\n"); } int main(void) { print *f1 = dosomething; print *f2 = &dosomething; f2(); (f1)(); (*f1)(); (**f2)(); (***f1)(); (****f2)(); (*****f1)(); }
Cela se comstack proprement sous:
gcc -O3 -g -Wall -Wextra -Werror -Wmissing-prototypes -Wssortingct-prototypes \ -Wold-style-definition -std=c99 xx.c -o xx
Je ne prétends pas que plusieurs écanvass est un bon style; ce n’est pas. C’est «étrange et (oui, vous pouvez le dire) pervers». Une seule suffit (et la seule écanvas s’adresse principalement aux personnes comme moi qui ont appris à programmer en C avant que la norme ne dise “c’est OK pour appeler une fonction via un pointeur sans utiliser la (*pointer_to_function)(arg1, arg2)
; vous peut simplement écrire pointer_to_function(arg1, arg2)
si vous aimez “). Oui, c’est bizarre. Non, aucun autre type (ou classe de types) ne présente le même comportement, Dieu merci.
La chose à propos des pointeurs de fonction est qu’ils sont des pointeurs de fonction ! 🙂 Voici comment vous obtenez votre troisième échantillon au travail:
#include typedef void (*print)(void); // ^ void do_something (void) { printf("Hello World\n"); } int main (void) { print pr; pr = do_something; // &do_something would also work. pr(); return 0; }
Que vous funcName
ou &funcName
, peu importe (en C au moins). La section 6.3.2.1 Lvalues, arrays and function designators
indique:
Un indicateur de fonction est une expression ayant le type de fonction. Sauf s’il s’agit de l’opérande de l’opérateur sizeof ou de l’opérateur unary &, un indicateur de fonction de type “type renvoyant une fonction” est converti en une expression de type “pointeur vers un type renvoyant une fonction”.
Il s’avère que, en C / C ++, funcname
et &funcname
donneront l’adresse de funcname
et pourront être affectés à une variable de pointeur de fonction. Ceci est en fait juste une bizarrerie de la façon dont la syntaxe a été conçue pour la ou les langues.
Comme C, C ++ a un pointeur sur des fonctions: void (*)()
par exemple, est un pointeur sur une fonction qui ne prend aucun argument et ne renvoie aucune valeur. Cependant, C ++ a également introduit des références aux fonctions void (&)()
et il existe des conversions implicites entre les deux (bien que je ne me souvienne pas exactement des règles).
Donc:
funcname
est une référence à la fonction &funcname
est un pointeur sur une fonction Notez que prendre l’adresse (ou une référence à) une fonction qui est surchargée nécessite un static_cast
du type exact (pour résoudre la surcharge).