OVH Cloud OVH Cloud

Pointeur de fonctions...

9 réponses
Avatar
Jean-Marc Bourguet
Quelqu'un peut-il m'expliquer pourquoi ceci

typedef void (*funcType)();

void foo(funcType);
void bar();

void test() {
foo(*******bar);
}

passe (au moins avec Como et Forte).

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

9 réponses

Avatar
Gabriel Dos Reis
Jean-Marc Bourguet writes:

| Quelqu'un peut-il m'expliquer pourquoi ceci
|
| typedef void (*funcType)();
|
| void foo(funcType);
| void bar();
|
| void test() {
| foo(*******bar);
| }
|
| passe (au moins avec Como et Forte).

Parce qu'un jour le comité C a décidé que si tu as un pointeur pf vers
une function, tu peux juste dire pf() au lieu de (*pf)() --
contrairement aux enseignments de K+R. L'idée était alors de dire
qu'un désignateur de fonction, sauf quelques situations particulières,
est un pointeur vers une fonction. Mais comme *pf est aussi
un designateur de fonction, tu peux dire **pf, ainsi de suite.
Bref, c'est stupide mais il faut vivre avec.

6.3.2.1 Lvalues, arrays, and function designators

[...]

[#4] A function designator is an expression that has
function type. Except when it is the operand of the sizeof
operator54) or the unary & operator, a function designator
with type ``function returning type'' is converted to an
expression that has type ``pointer to function returning
type''.

-- Gaby
Avatar
Alexandre
bonjour,

Quelqu'un peut-il m'expliquer pourquoi ceci

typedef void (*funcType)();

void foo(funcType);
void bar();

void test() {
foo(*******bar);
}

passe (au moins avec Como et Forte).


je pense parce que l'opérateur d'indirection (*) n'a pas d'effet réel sur un
pointeur de fonction. Dans ton cas, bar représente l'adresse de la fonction,
&bar aussi, et je suppute que *bar aussi... Je pense donc que les écritures
foo(bar)
foo(&bar)
foo(*bar)
sont équivalentes.

Avatar
Horst Kraemer
On 28 May 2004 18:06:56 +0200, Jean-Marc Bourguet
wrote:


Quelqu'un peut-il m'expliquer pourquoi ceci

typedef void (*funcType)();

void foo(funcType);
void bar();

void test() {
foo(*******bar);
}

passe (au moins avec Como et Forte).

A+


D'après la norme du langage C toute expression qui désigne une
fonction (c.a.d. une lvalue du type fonction) à l'exception des cas ou
l'opérateur & est appliqué à la fonction - est convertie
automatiquement en pointeur vers fonction qui pointe vers cette
fonction, c.a.d. la fonction est convertie automatiquement en sa
propre adresse.

D'après la norme du langage C++ toute expression qui désigne une
fonction à l'exception des cas ou l'opérateur & ou l'opérateur d'appel
() est appliqué à la fonction est convertie automatiquement en
pointeur vers fonction qui pointe vers cette fonction.

Cela veut dire que dans les deux langages l'expression

*****bar

comme argument d'une fonction subit les conversions implicites
intercalées suivantes

&*&*&*&*&*&bar

_avant_ d'étre passée.


Donc le type de l'expression *****bar est en fait les type de
l'expression &*&*&*&*&*&bar - et ce type est le même que le type de
&bar. Les * répétés n'ont donc aucun effet parce que les résultat de
chaque * qui produit une expression du type 'fonction' est reconverti
immédiatement en pointeur vers fonction.

En C, l'expression 'bar' est *toujours* convertie automatiquement en
pointeur sauf dans l'expresion &bar - même dans l'expression bar(). La
raison est que l'opérande de l'opérateur () d'appel doit avoir le type
'pointeur vers fonction' en C. En C++ l'opérande de l'opérateur ()
peut être une fonction _ou_ un pointeur vers fonction. Donc
formellement en C++ 'bar' n'est pas convertie en pointeur dans
l'expression bar() - mais cette différence formelle entre C et C++ ne
ne se voit pas.

Le résultat est que dans les deux langages on peut appeler la fonction
'bar' après les définitions suivantes

void bar(void) {}
void (*f) (void) = bar; /* ou = &bar */

par chaqu'une des expressions suivantes:

bar()

Légal en C++ parce que () accepte une fonction et légal en C parce que
() n'accepte que des pointeurs vers fonctions mais 'bar' est converti
automatiquement en son adresse &bar.

(*bar)();

*bar est légal dans les deux langages bien que bar soit une fonction
parce que bar est converti automatiquement en &bar avant l'application
de l'opérateur *. En C *bar (c.a.d. *&bar) est reconverti en &*bar
(c.a.d. en &*&bar) avant l'appel et en C++ l'opérateur accepte la
fonction *bar (*&bar).

(**bar)();
(***bar)();
...

Voir l'explication plus haut
...
(&bar)()

Légal en C parce que &bar a le type exact qu'il faut pour un appel.
Légal en C++ parce l'opérateur () accepte ou bien une fonction ou bien
un pointeur.

(&&bar)()

Erreur dans les deux langages ;-)

...

f();

f a le bon type en C et un des bons types en C++

(*f)();

En C *f est reconconverti en &*f pour l'appel et en C++ *f a un des
bons types pour l'appel.

(**f)();
...

voir plus haut.


--
Horst

Avatar
Jean-Marc Bourguet
Gabriel Dos Reis writes:

Jean-Marc Bourguet writes:

| Quelqu'un peut-il m'expliquer pourquoi ceci
|
| typedef void (*funcType)();
|
| void foo(funcType);
| void bar();
|
| void test() {
| foo(*******bar);
| }
|
| passe (au moins avec Como et Forte).

Parce qu'un jour le comité C a décidé que si tu as un pointeur pf v ers
une function, tu peux juste dire pf() au lieu de (*pf)()
--


Je suppose que tu voulais écrire pf = f au lieu de pf = &f.
C'est bien ce à quoi je pensais mais la conséquence est
amusante... Enfin je suppose que nous sommes d'accord que
l'écriture la plus claire est
foo(&bar);

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index. html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
Loïc Joly
Jean-Marc Bourguet wrote:

Enfin je suppose que nous sommes d'accord que
l'écriture la plus claire est
foo(&bar);


Tout comme le plus naturel est d'écrire :

cout << "Hello world!" << &endl;

;p ?

--
Loïc

Avatar
Michel Michaud
Dans news:, Jean-Marc
Enfin je suppose que nous sommes d'accord que
l'écriture la plus claire est
foo(&bar);


Pas pour moi... foo(bar); est la plus claire... On est en
C++ et je ne veux même pas modifié bar... :-)

(mais on ne repartira pas une discussion là-dessus, chacun
a son opinion et je ne voulais simplement pas laisser ton
message passé sans contestation)

--
Michel Michaud
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/

Avatar
Gabriel Dos Reis
Jean-Marc Bourguet writes:

| l'écriture la plus claire est
| foo(&bar);

Oui. Et c'est ce que Le Père a choisi pour les fonctions membres
non-statiques.

J'ai découvert assez récemment que Core a réussi à encore inventer des
trucs à dormir debout.

typedef void fun_t();

struct A {
fun_t foo; // foo fonction membre non-statique
};

A::foo est de type void (), mais &A::foo est de type
void (A::*)() ; et bien sûr pour rendre le truc plus amusant,
bien que A::foo soit de type void (), on ne peut pas la lier
à une référence de type void (&) -- bien qu'on puisse le
faire avec les autres fonctions de ce type. Groumph.

Cette invention de Core est une décision contraire à une
note explicative de l'ARM. Groumph.

-- Gaby
Avatar
Jean-Marc Bourguet
Loïc Joly writes:

Jean-Marc Bourguet wrote:

Enfin je suppose que nous sommes d'accord que
l'écriture la plus claire est
foo(&bar);


Tout comme le plus naturel est d'écrire :

cout << "Hello world!" << &endl;

;p ?


Ce n'est pas idiomatique, mais c'est moins clair.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index. html
Site de usenet-fr: http://www.usenet-fr.news.eu.org


Avatar
Loïc Joly
Gabriel Dos Reis wrote:

Jean-Marc Bourguet writes:

| l'écriture la plus claire est
| foo(&bar);

Oui. Et c'est ce que Le Père a choisi pour les fonctions membres
non-statiques.

J'ai découvert assez récemment que Core a réussi à encore inventer des
trucs à dormir debout.


Ils préparent l'IOC++CC...

--
Loïc