Pourquoi ne pointeur de fonction des définitions de travail avec un certain nombre de signes & '&' ou des astérisques"*'?
Pourquoi faire les travaux suivants?
void foo() {
cout << "Foo to you too!\n";
};
int main() {
void (*p1_foo)() = foo;
void (*p2_foo)() = *foo;
void (*p3_foo)() = &foo;
void (*p4_foo)() = *&foo;
void (*p5_foo)() = &*foo;
void (*p6_foo)() = **foo;
void (*p7_foo)() = **********************foo;
(*p1_foo)();
(*p2_foo)();
(*p3_foo)();
(*p4_foo)();
(*p5_foo)();
(*p6_foo)();
(*p7_foo)();
}
Vous devez vous connecter pour publier un commentaire.
Il ya quelques morceaux de ce qui permet à tous de ces combinaisons d'opérateurs de travailler de la même façon.
La raison fondamentale de l'ensemble de ces travaux est qu'une fonction (comme
foo
) est implicitement converti en un pointeur vers la fonction. C'est pourquoivoid (*p1_foo)() = foo;
travaux:foo
est implicitement converti en un pointeur à lui-même et que le pointeur est attribué àp1_foo
.Unaire
&
, lorsqu'il est appliqué à une fonction renvoie un pointeur vers la fonction, tout comme il donne l'adresse d'un objet lorsqu'il est appliqué à un objet. Pour les pointeurs de fonctions ordinaires, il est toujours redondante, car de l'implicite de la fonction à la fonction de pointeur de la conversion. En tout cas, c'est pourquoivoid (*p3_foo)() = &foo;
œuvres.Unaire
*
, lorsqu'il est appliqué à un pointeur de fonction, les rendements de la pointe-à la fonction, tout comme il donne de la pointe-à l'objet lorsqu'il est appliqué à un simple pointeur vers un objet.Ces règles peuvent être combinés. Considérez votre avant-dernier exemple,
**foo
:foo
est implicitement converti en un pointeur sur lui-même et le premier*
est appliquée à la fonction de pointeur, rendement de la fonctionfoo
de nouveau.*
est appliquée, de nouveau rendement de la fonctionfoo
.Vous pouvez ajouter autant de
*
s que vous le souhaitez, le résultat est toujours le même. Le plus*
s, plus on rit.On peut aussi considérer votre cinquième exemple,
&*foo
:foo
est implicitement converti en un pointeur sur lui-même; unaire*
est appliqué, donnantfoo
de nouveau.&
est appliqué àfoo
, ce qui donne un pointeur versfoo
, qui est affectée à la variable.La
&
ne peut être appliqué à une fonction, et non à une fonction qui a été converti en un pointeur de fonction (à moins, bien sûr, la fonction de pointeur est une variable, auquel cas le résultat est un pointeur vers un pointeur à une fonction; par exemple, vous pourriez ajouter à votre listevoid (**pp_foo)() = &p7_foo;
).C'est pourquoi
&&foo
ne fonctionne pas:&foo
n'est pas une fonction, c'est un pointeur de fonction qui est une rvalue. Cependant,&*&*&*&*&*&*foo
serait, comme le ferait&******&foo
, parce que dans ces deux expressions de la&
est toujours appliqué à une fonction et non pas à une rvalue pointeur de fonction.Notez également que vous n'avez pas besoin d'utiliser le unaire
*
de faire l'appel via le pointeur de fonction; les deux(*p1_foo)();
et(p1_foo)();
avoir le même résultat, à nouveau en raison de la fonction à la fonction de pointeur de conversion.&foo
prend l'adresse defoo
, ce qui résulte en un pointeur de fonction de pointage àfoo
, que l'on pourrait attendre.&
opérateurs pour les objets: étant donnéint p;
,&p
renvoie un pointeur versp
et est une rvalue expression; la&
opérateur nécessite une lvalue expression.*
's, le moins joyeux.p1_foo()
au lieu de(p1_foo)()
, mais le "extra" les parenthèses de la rendre plus la syntaxe est similaire à(*p1_foo)()
, à qui nous faisons une comparaison.&*
annuler les uns les autres (6.5.3.2):"The unary & operator yields the address of its operand."
/--/"If the operand is the result of a unary * operator, neither that operator nor the & operator is evaluated and the result is as if both were omitted, except that the constraints on the operators still apply and the result is not an lvalue."
.Je pense que c'est également utile de se rappeler que C est juste une abstraction de la machine et c'est l'un des endroits où l'abstraction est une fuite.
Du point de vue de l'ordinateur, une fonction est une adresse mémoire qui, s'il est exécuté, il s'acquitte d'autres instructions. Donc une fonction en C est lui-même modélisé comme une adresse, ce qui a probablement conduit à la conception qu'une fonction est "identique" à l'adresse qu'il indique.