OVH Cloud OVH Cloud

Pointeurs vers fonctions

54 réponses
Avatar
Pierre Maurette
Bonjour,
Mon problème est peut-être plus C que C++, mais je le fais facilement
apparaître avec new[], et de plus c'est la réponse de la norme C++ qui
m'intéresse le plus.
Si on définit une variable pointeur de fonction :
int(*pF)(double, double) = NULL;
on a la facilité d'utiliser ou non, indifféremment, les opérateurrs * et & ,
ou plus exactement on a exceptionnellement la possibilité de les omettre :
int fonct(double x, double y) {return (int)(x * y);}
...
pF = &fonct;
pF = fonct;
...
x = pF(4.0, 2.0);
x = (*pF)(4.0, 2.0);

Question : qu'en dit la norme ? (pas pu trouver)

Si je désire un tableau de fonctions dont la taile sera déterminée à
l'exécution, je dois faire :
int(**pF)(double, double) = NULL;
Ensuite, en C comme en C++ :
int n = 12;
pF = (int(**)(double, double))malloc(n * sizeof(int(*)(double, double)));
x = pF[4](4.0, 2.0);
Pas beau, puisque pF n'a pas le même type dans les deux lignes, mais logique
au vu de ce qui précède.
Passons au new[] :
pF = new (int(*)(double, double))[n];
La famille du Gnou accepte, et le résultat est celui attendu. Chez Borland,
c'est non., conversion de type impossible
Les Gnou interprètent pF en fonction de l'appel de malloc() ou de new[], pas
Borland. Je ne suis pas contre, je préfèrerais même que ne soient pas
autorisées les facilités initiales, donc que le typedef s'impose de
lui-même.
Question : Qu'en dit la norme ? Qui a raison ?

Bien entendu, un typedef s'impose, et tout rentre dans l'ordre.

typedef int(*Fonc_Type)(double, double);
Fonc_Type* pF1;
Fonc_Type* pF2;
int n = 12;
pF1 = (Fonc_Type*) malloc(n * sizeof(Fonc_Type));
pF2 = new Fonc_Type[n];
pF1[5] = f1;
pF2[6] = f2;

Merci pour vous lulières,
Pierre

4 réponses

2 3 4 5 6
Avatar
Michel Michaud
Dans news:,
"Michel Michaud" wrote in message
news:<NXzMb.6253$...
Dans news:,


[...]
Dans la contexte de B, ça se comprend. En revanche, je ne sais pas
pourquoi, quand ils ont passé de B en C, ils ont changé les
fonctions, et non les tableaux. Logiquement, avec le typage plus
fort de C, on s'attendrait à ce que les deux changent.


Alors tu penses comme moi, au niveau de l'uniformité.


Non. En B, il y avait une sorte d'uniformité. Quand ils ont


Oui, et en C « on s'attendrait à ce que les deux changent ».
Donc on voudrait l'uniformité. On pense la même chose.

introduit le typage, pour en faire C, ils en ont introduit une
autre sorte. Sauf pour des pointeurs. Permettre pf() n'améliore pas
l'uniformité -- il crée deux exceptions (deux cas des types de
seconde classe), à la place d'une.


Oui oui, on pourrait avoir eu l'uniformité dans l'autre sens (en
obligeant (*pf)()). Ça aurait été mieux.

Alors je répète, tu penses comme moi : il y a un certain lien
entre les adresses de tableaux et celles des fonctions (Gabriel
ne voit pas de la même façon et c'est légitime), alors pour
l'uniformité, en passant de B à C, c'est surprenant que les deux
n'aient pas changé.

Le fait que ANSI C ait corrigé cette uniformité dans le bon sens
ou dans le mauvais, c'est une autre histoire (je suis content
qu'on ait l'uniformité, mais j'aurai préféré l'avoir autrement
et ce sens je crois que je suis d'accord aussi avec Gabriel).

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



Avatar
kanze
"Michel Michaud" wrote in message
news:<CgYMb.10145$...
Dans news:,
"Michel Michaud" wrote in message
news:<NXzMb.6253$...
Dans news:,


[...]
Dans la contexte de B, ça se comprend. En revanche, je ne sais pas
pourquoi, quand ils ont passé de B en C, ils ont changé les
fonctions, et non les tableaux. Logiquement, avec le typage plus
fort de C, on s'attendrait à ce que les deux changent.


Alors tu penses comme moi, au niveau de l'uniformité.


Non. En B, il y avait une sorte d'uniformité. Quand ils ont


Oui, et en C « on s'attendrait à ce que les deux changent ». Donc on
voudrait l'uniformité. On pense la même chose.


Ce n'est pas tellement une question des deux. Le typage en B est
radicalement différent qu'en C. Ce qui est uniforme en B ne l'est pas en
C, et vice versa.

introduit le typage, pour en faire C, ils en ont introduit une autre
sorte. Sauf pour des pointeurs. Permettre pf() n'améliore pas
l'uniformité -- il crée deux exceptions (deux cas des types de
seconde classe), à la place d'une.


Oui oui, on pourrait avoir eu l'uniformité dans l'autre sens (en
obligeant (*pf)()). Ça aurait été mieux.

Alors je répète, tu penses comme moi : il y a un certain lien entre
les adresses de tableaux et celles des fonctions (Gabriel ne voit pas
de la même façon et c'est légitime), alors pour l'uniformité, en
passant de B à C, c'est surprenant que les deux n'aient pas changé.


Non. Cette fois-ci, je suis d'accord ave Gabriel. En C, il n'y a pas de
véritable lien entre les adresses de tableaux et celles de fonctions.
Les seuls liens entre les deux sont historiques -- le fait qu'en B, il
fallait traiter ces objets-là comme des pointeurs (parce qu'ils ne
tenaient pas dans un mot machine), et ensuite, le fait qu'il y a eu une
extension répandue qui les traitait pareils. Quant au premier argument,
il se serait appliqué aux struct aussi, s'il y en avait eu en B. Et la
raisonnement de B ne s'applique pas du tout à C.

Je ne sais pas pourquoi Kernighan et Richie ont fait les choix qu'ils
ont fait. Je suppose que d'une part, la définition de l'indexation en C
vient directement de B, et implique une conversion implicite du tableau
en pointeur, et de l'autre, des considérations de performance, qui fait
qu'on préfère passer les tableau « par référence », explique le choix.
Et on remarque tout de suite que le premier argument ne s'applique
qu'aux tableaux.

Le fait que ANSI C ait corrigé cette uniformité dans le bon sens ou
dans le mauvais, c'est une autre histoire (je suis content qu'on ait
l'uniformité, mais j'aurai préféré l'avoir autrement et ce sens je
crois que je suis d'accord aussi avec Gabriel).


Le comité ANSI n'a pas corrigé une uniformité ; il en a introduit une
autre exception à l'uniformité. À la rigueur, l'exception en ce qui
concerne les tableaux s'expliquent par la façon qu'est définie
l'indexation ; à mon avis, c'est aussi un défaut, mais c'est comme ça,
et la sémantique de l'indexation en C exige la conversion d'un tableau
en pointeur.

Le comité ANSI n'a pas cherché à faire un langage nouveau, simple et
élégant. Les buts fixés étaient plutôt pragmatiques. Il y avait beaucoup
de compilateurs qui acceptaient l'extension (sans doute sous l'influence
de B ou de BCPL) et le permettre ne pouvait pas provoquer des problèmes
dans des programmes existants qui ne s'en servaient pas. Du point de vue
pragmatique, donc, la solution la plus simple était de le permettre.

--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16




Avatar
Michel Michaud
Dans news:,
"Michel Michaud" wrote in message
news:<CgYMb.10145$...
Dans news:,
"Michel Michaud" wrote in message
news:<NXzMb.6253$...
Dans news:,
Dans la contexte de B, ça se comprend. En revanche, je ne sais
pas pourquoi, quand ils ont passé de B en C, ils ont changé les
fonctions, et non les tableaux. Logiquement, avec le typage plus
fort de C, on s'attendrait à ce que les deux changent.


Alors tu penses comme moi, au niveau de l'uniformité.


Non. En B, il y avait une sorte d'uniformité. Quand ils ont


Oui, et en C « on s'attendrait à ce que les deux changent ». Donc
on voudrait l'uniformité. On pense la même chose.


Ce n'est pas tellement une question des deux. Le typage en B est
radicalement différent qu'en C. Ce qui est uniforme en B ne l'est
pas en C, et vice versa.


En tout cas. Disons simplement que, uniformité ou pas, les
règles de C et de C++ sont un mystère (en particulier quand on
pense aux pointeurs vers fonction membre vs pointeurs de fonction).

introduit le typage, pour en faire C, ils en ont introduit une
autre sorte. Sauf pour des pointeurs. Permettre pf() n'améliore
pas l'uniformité -- il crée deux exceptions (deux cas des types de
seconde classe), à la place d'une.


Oui oui, on pourrait avoir eu l'uniformité dans l'autre sens (en
obligeant (*pf)()). Ça aurait été mieux.

Alors je répète, tu penses comme moi : il y a un certain lien entre
les adresses de tableaux et celles des fonctions (Gabriel ne voit
pas de la même façon et c'est légitime), alors pour l'uniformité,
en passant de B à C, c'est surprenant que les deux n'aient pas
changé.


Non. Cette fois-ci, je suis d'accord ave Gabriel. En C, il n'y a
pas de véritable lien entre les adresses de tableaux et celles de
fonctions. Les seuls liens entre les deux sont historiques -- le


C'est un lien. Je suis aussi d'accord avec Gabriel et avec toi :
dans le fond, il n'y a pas de lien. Mais dans les faits, il y en
a deux : historique et syntaxique.

[...]
Le comité ANSI n'a pas cherché à faire un langage nouveau, simple et
élégant. Les buts fixés étaient plutôt pragmatiques. Il y avait
beaucoup de compilateurs qui acceptaient l'extension (sans doute
sous l'influence de B ou de BCPL) et le permettre ne pouvait pas
provoquer des problèmes dans des programmes existants qui ne s'en
servaient pas. Du point de vue pragmatique, donc, la solution la
plus simple était de le permettre.


Et la raison pour laquelle certains compilateurs l'acceptaient
n'est-elle pas la même qui auraient permis d'accepter aussi la
syntaxe similaire pour les pointeurs sur fonctions ? À ce que je
sache, il n'y a pas que VC qui l'acceptait (et même s'il n'y
avait que VC, c'est un gros joueur... considérons le fait que
static const int membre= 123; a été accepté parce que Borland
le permettait, si j'ai bien compris...).

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





Avatar
kanze
"Michel Michaud" wrote in message
news:<vdANb.3706$...
Dans news:,
"Michel Michaud" wrote in message
news:<CgYMb.10145$...
Dans news:,
"Michel Michaud" wrote in message
news:<NXzMb.6253$...
Dans news:,
Dans la contexte de B, ça se comprend. En revanche, je ne sais
pas pourquoi, quand ils ont passé de B en C, ils ont changé les
fonctions, et non les tableaux. Logiquement, avec le typage plus
fort de C, on s'attendrait à ce que les deux changent.


Alors tu penses comme moi, au niveau de l'uniformité.


Non. En B, il y avait une sorte d'uniformité. Quand ils ont


Oui, et en C « on s'attendrait à ce que les deux changent ». Donc
on voudrait l'uniformité. On pense la même chose.


Ce n'est pas tellement une question des deux. Le typage en B est
radicalement différent qu'en C. Ce qui est uniforme en B ne l'est
pas en C, et vice versa.


En tout cas. Disons simplement que, uniformité ou pas, les règles de C
et de C++ sont un mystère (en particulier quand on pense aux pointeurs
vers fonction membre vs pointeurs de fonction).


En ce qui concerne le systèmes de types, je n'irais pas jusqu'à dire que
les règles soit un mystère. Dans l'ensemble, il y a une certaine
cohérence, mais avec des exceptions : surtout, les tableaux (de type C)
et le pointeur nul. La liberté de faire pf() en présente une troisième,
avec la différence près (par rapport aux deux précédantes) que je ne
suis pas obligé à mon servir.

[...]
Le comité ANSI n'a pas cherché à faire un langage nouveau, simple et
élégant. Les buts fixés étaient plutôt pragmatiques. Il y avait
beaucoup de compilateurs qui acceptaient l'extension (sans doute
sous l'influence de B ou de BCPL) et le permettre ne pouvait pas
provoquer des problèmes dans des programmes existants qui ne s'en
servaient pas. Du point de vue pragmatique, donc, la solution la
plus simple était de le permettre.



[Je suppose ici que tu parles des pointeurs à des fonctions membre ;
je ne vois pas de sens dans tes propos autrement. Moi, je parlais
encore des pointeurs à fonction simple, et du C.]

Et la raison pour laquelle certains compilateurs l'acceptaient
n'est-elle pas la même qui auraient permis d'accepter aussi la syntaxe
similaire pour les pointeurs sur fonctions ? À ce que je sache, il n'y
a pas que VC qui l'acceptait (et même s'il n'y avait que VC, c'est un
gros joueur...


Je crois que la raison pourquoi certains compilateurs l'acceptent, c'est
d'être compatible avec VC++.

considérons le fait que static const int membre= 123; a été accepté
parce que Borland le permettait, si j'ai bien compris...).


C'est la première fois que j'entends ça. Je croyais qu'il avait été
accepté parce qu'il répondissait à un problème réel : déclarer un membre
d'un type entier précis qui était aussi un « constant integral
expression », et qui pourrait servir par exemple comme dimension d'un
tableau.

--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16






2 3 4 5 6