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

10 réponses

2 3 4 5 6
Avatar
kanze
"Michel Michaud" wrote in message
news:<1fZKb.45704$...
Dans news:,
D'après la rationnale (http://www.lysator.liu.se/c/rat/title.html) :


Merci pour cette adresse James... Je pensais l'avoir (ou une autre
semblable), mais il semble que non...


Si tu t'intéresses un peu au C, ne serait-ce que pour des raisons
historiques, il y a un tas de liens intéressants à
http://www.lysator.liu.se/c/. C'est là où j'ai trouvé celui-là.

On remarque que même pour le comité C, la forme usuelle (ou
« conventionnelle »), c'est (*pf)().


Effectivement, mais j'avais toujours compris qu'elle était
simplement préférée et non la seule initialement.


« Conventionnelle » (au moins en anglais), c'est bien plus fort que
préféré.

En ce qui concerne la motivation de base, je suis prèsque sûr que
l'extention était assez répandue -- je m'en souviens de son
existance bien avant C90, et j'avoue avoir été étonné quand Gaby a
dit qu'elle n'était pas dans K&R 1.


Toi aussi ? Bien :-)


Oui. Ça fait au moins vingt ans depuis que j'ai lu K&R. Depuis que je me
rappelle, pf() était « légal », et utilisé par certains programmeurs. Je
ne l'ai jamais aimé, je ne m'en suis jamais servi, mais je le croyais
légal depuis le début.

Je n'ai fait du C pré-ANSI que pendant 6-7 ans, mais il me semble bien
que mon compilateur acceptait pf() quand j'ai commencé à en faire
usage. Était-ce un compilateur ANSI C ou simplement une possibilité
offerte par mon compilateur, je ne sais pas...


Ça dépendrait de la date, je crois. Mais d'après mes souvenirs, il
marchait avec le pCC de Johnson (qui était la deuxième implémentation de
C). Au moins que ce soit un apport de l'équipe de Berkley. (Le
compilateur C de Berkley se basait bien sur le pCC de Johnson, mais ils
ont changé un certain nombre de choses.)

[...]
Je ne crois pas qu'elle ait fait l'unanimité dans la communauté C
non plus. Le problème, c'est que c'était une pratique existante avec
certains compilateurs.


J'avoue que j'ai toujours trouvé le déréférencement (et la prise
d'adresse) explicite un peu artificiel. L'analogie avec les tableaux
me semble vraiment naturelle.


C'est vrai que les tables présentent la même anomalie. Certains (dont
moi-même) considèrent ça un défaut aussi. Mais l'anomalie, dans le cas
des tables, s'explique par l'héritage -- C dérive de B (et
ultérieurement de BCPL), où tout symbole représente un mot machine. En
B, quand tu déclarais une table, le compilateur allouait bien la table,
mais aussi un mot initialisé avec l'adresse de la table. Et ce que le
symbole désignait, c'était ce mot (dont on se servait comme un
pointeur), et non la table.

Je ne sais pas comment B traitait les pointeurs à des fonctions, ni même
s'il en avait. Mais je suis assez certain que le nom de la fonction
désignait la fonction, et non un pointeur à la fonction -- le méchanisme
utilisé pour les tables n'entraient pas en jeu.

Est-ce que j'aurais eu une façon de voir qui vient d'autre langage ?
Je ne me souviens plus du passage de fonction en Pascal...


Je ne suis plus très sûr, mais il me semble que c'était quelque chose du
genre :
VAR pf : ^PROCEDURE (...) ;
utilisé :
pf = nomDeProcedure ;
pf^ (...) ;
Mais ça fait très longtemps, et c'est tout très vague. (J'ai la
photocopie de la norme Pascal quelque part dans des cartons chez moi,
mais je ne saurais le trouver comme ça.)

The grammaire pour Modula-2
(http://cui.unige.ch/db-research/Enseignement/analyseinfo/Modula2/BNFindex.html)
dit que la déclaration serait plutôt :
VAR pf : POINTER TO PROCEDURE ...
mais que la syntaxe de l'appel est bien le même. Et je n'arrive pas à
trouver la syntaxe de l'affectation.

Je ne sais pas si Modula-2 a changé par rapport à Pascal, ou si c'est un
trou dans ma mémoire -- probablement le dernier.

Quand même :

int UneFct(int n) { ... }
int v[10];

void Naturelle(int v[], int F(int)) // Pointeurs implicites
{
v[2]= F(v[4]);
}

void MoinsNaturelle(int *pv, int (*pF)(int)) // Explicites
{
v[2]= (*pF)(v[4]); // Et non pas (*v)[2], etc.
}

int main()
{
Naturelle(v, UneFct);
MoinsNaturelle(v, &UneFct); // &v ? ...

// N.B. Évidemment on peut appeler les deux fonctions
// de la même façon...
}

En fait, si j'avais Ritchie devant moi, je lui demanderais pourquoi,
dans son langage original, on peut écrire v pour &v[0] au lieu
d'exiger & comme pour les fonctions... La solution ANSI me semble plus
uniforme.


En somme, ce que tu veux c'est d'étendre le défaut des tableaux à des
fonctions aussi.

La motivation pour cette anomalie de comportement avec les tableaux est
due à l'histoire ; voir la spécification de B, et les documents
historiques à http://www.lysator.liu.se/c/. Mais c'est un défaut :
pourquoi est-ce que les tableaux fonctionnent différemment que les
autres types ?

--
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
kanze
Gabriel Dos Reis wrote in message
news:...

[...]
| Ça ne concerne que mes activités professionnelles. À titre de
| curiosité d'adolescent, j'ai appris l'assembleur 1401 en 1965, mais
| je m'en suis jamais réelement servi. Mes premiers contacts avec C++
| était aussi privé, aux alentours de 1987.

Une version que je possédais jusqu'à présent aux alentours de 1990. Je
remets ma base de données à jour.


Note bien alors que mes premiers contacts étaient pûrement théoriques,
et que je n'avais pas accès à un compilateur C++ à l'époque.

Et en passant, je suis intrigué que tu maintiens une base de données sur
des personnes comme ça. Ça me fait penser à la KGB.

--
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
Gabriel Dos Reis
writes:

| > > En ce qui concerne la motivation de base, je suis prèsque sûr que
| > > l'extention était assez répandue -- je m'en souviens de son
| > > existance bien avant C90, et j'avoue avoir été étonné quand Gaby a
| > > dit qu'elle n'était pas dans K&R 1.
|
| > Toi aussi ? Bien :-)
|
| Oui. Ça fait au moins vingt ans depuis que j'ai lu K&R. Depuis que je me
| rappelle, pf() était « légal », et utilisé par certains programmeurs. Je
| ne l'ai jamais aimé, je ne m'en suis jamais servi, mais je le croyais
| légal depuis le début.

Toutes les versions officielles de GCC à ce jour sont écrites en C K+R.
(Cela changera avec GCC-3.4.0) Et on n'utilisait pas « pf() »
précisement parce que ce n'est pas du C K+R ; et je sais aussi qu'on a
eu des erreurs de bootstrap avec des compilateurs C K+R encore en
survis -- heureusement, ces bêtes deviennent de plus en plus rare (et
en tout cas, ne sont plus considérées dans les futures versions de GCC).
Quand on est passé à C90, la première chose que certains ont fait,
c'est de convertir les (*pf)(args) en pf(args).

-- Gaby
Avatar
Gabriel Dos Reis
writes:

| Gabriel Dos Reis wrote in message
| news:...
|
| [...]
| > | Ça ne concerne que mes activités professionnelles. À titre de
| > | curiosité d'adolescent, j'ai appris l'assembleur 1401 en 1965, mais
| > | je m'en suis jamais réelement servi. Mes premiers contacts avec C++
| > | était aussi privé, aux alentours de 1987.
|
| > Une version que je possédais jusqu'à présent aux alentours de 1990. Je
| > remets ma base de données à jour.
|
| Note bien alors que mes premiers contacts étaient pûrement théoriques,
| et que je n'avais pas accès à un compilateur C++ à l'époque.
|
| Et en passant, je suis intrigué que tu maintiens une base de données sur
| des personnes comme ça.

Mais *toi* aussi tu en as sur des personnes ! Et tu les utilises tous
les jours. Visiblement, cela ne t'intrigue pas lorsque c'est toi qui
le fait.

| Ça me fait penser à la KGB.

et pas à la CIA ni à la DST. C'est intéressant.

-- Gaby
Avatar
Michel Michaud
Dans news:,
"Michel Michaud" wrote in message
news:<1fZKb.45704$...
En fait, si j'avais Ritchie devant moi, je lui demanderais
pourquoi, dans son langage original, on peut écrire v pour &v[0]
au lieu d'exiger & comme pour les fonctions... La solution ANSI
me semble plus uniforme.


En somme, ce que tu veux c'est d'étendre le défaut des tableaux à
des fonctions aussi.


Non, pas du tout. Je préfère l'uniformité, alors j'obligerais
plutôt &v[0]. Mais évidemment, c'est difficile étant donné la
définition de [] !

La motivation pour cette anomalie de comportement avec les tableaux
est due à l'histoire ; voir la spécification de B, et les documents
historiques à http://www.lysator.liu.se/c/. Mais c'est un défaut :
pourquoi est-ce que les tableaux fonctionnent différemment que les
autres types ?


Bien alors, j'aimerais l'uniformité avec les fonctions ! Ah ? On
l'a ? Eh ben, on discute pour rien alors :-)

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


Avatar
kanze
Gabriel Dos Reis wrote in message
news:...
writes:

| > > En ce qui concerne la motivation de base, je suis prèsque sûr
| > > que l'extention était assez répandue -- je m'en souviens de son
| > > existance bien avant C90, et j'avoue avoir été étonné quand Gaby
| > > a dit qu'elle n'était pas dans K&R 1.

| > Toi aussi ? Bien :-)

| Oui. Ça fait au moins vingt ans depuis que j'ai lu K&R. Depuis que je me
| rappelle, pf() était « légal », et utilisé par certains programmeurs. Je
| ne l'ai jamais aimé, je ne m'en suis jamais servi, mais je le croyais
| légal depuis le début.

Toutes les versions officielles de GCC à ce jour sont écrites en C
K+R. (Cela changera avec GCC-3.4.0) Et on n'utilisait pas « pf() »
précisement parce que ce n'est pas du C K+R ;


Et que la portabilité est importante. Et que vous l'avez compilé avec un
tas de compilateurs C différents.

Comme j'ai dit, il fut un temps où l'attitude de beaucoup de
programmeurs C, c'est que tout le monde est un VAX. Or, sur le
compilateur VAX de l'époque, apparamment, pf() marchait.

--
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
kanze
Gabriel Dos Reis wrote in message
news:...
writes:

| Gabriel Dos Reis wrote in message
| news:...

| [...]
| > | Ça ne concerne que mes activités professionnelles. À titre de
| > | curiosité d'adolescent, j'ai appris l'assembleur 1401 en 1965,
| > | mais je m'en suis jamais réelement servi. Mes premiers contacts
| > | avec C++ était aussi privé, aux alentours de 1987.

| > Une version que je possédais jusqu'à présent aux alentours de
| > 1990. Je remets ma base de données à jour.

| Note bien alors que mes premiers contacts étaient pûrement
| théoriques, et que je n'avais pas accès à un compilateur C++ à
| l'époque.

| Et en passant, je suis intrigué que tu maintiens une base de données
| sur des personnes comme ça.

Mais *toi* aussi tu en as sur des personnes !


Qu'est-ce qui te fait croire ça ? Je sais que tu es plus jeune que moi,
mais c'est tout, mais j'ai aucune idée de ce que tu as fait
professionnellement. (D'après tes attitudes, je peux conclure que tu
n'as jamais travaillé sur un gros projet d'une certaine qualité. Mais
c'est une connaissance indirecte.)

Et tu les utilises tous les jours.


Quand, par exemple ?

--
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
Gabriel Dos Reis
writes:

| Gabriel Dos Reis wrote in message
| news:...
| > writes:
|
| > | Gabriel Dos Reis wrote in message
| > | news:...
|
| > | [...]
| > | > | Ça ne concerne que mes activités professionnelles. À titre de
| > | > | curiosité d'adolescent, j'ai appris l'assembleur 1401 en 1965,
| > | > | mais je m'en suis jamais réelement servi. Mes premiers contacts
| > | > | avec C++ était aussi privé, aux alentours de 1987.
|
| > | > Une version que je possédais jusqu'à présent aux alentours de
| > | > 1990. Je remets ma base de données à jour.
|
| > | Note bien alors que mes premiers contacts étaient pûrement
| > | théoriques, et que je n'avais pas accès à un compilateur C++ à
| > | l'époque.
|
| > | Et en passant, je suis intrigué que tu maintiens une base de données
| > | sur des personnes comme ça.
|
| > Mais *toi* aussi tu en as sur des personnes !
|
| Qu'est-ce qui te fait croire ça ?

coche la case qui va bien :

( ) ou bien tu joues à l'idiot
( ) ou bien tu n'as vraiment pas de mémoire

| Je sais que tu es plus jeune que moi,

Donc, tu as une base de données -- cette connaissance que tu as est
stockée quelque part !

| mais c'est tout,

mais une base de données n'est pas forcément sophistiquée ni pleine
-- elle peut être vide.

| mais j'ai aucune idée de ce que tu as fait
| professionnellement. (D'après tes attitudes, je peux conclure que tu
| n'as jamais travaillé sur un gros projet d'une certaine qualité. Mais
| c'est une connaissance indirecte.)
|
| > Et tu les utilises tous les jours.
|
| Quand, par exemple ?

ta mémoire -- lorsque tu te prends pour un griot.

-- Gaby
Avatar
kanze
"Michel Michaud" wrote in message
news:<lnfLb.72095$...
Dans news:,
"Michel Michaud" wrote in message
news:<1fZKb.45704$...
En fait, si j'avais Ritchie devant moi, je lui demanderais
pourquoi, dans son langage original, on peut écrire v pour &v[0] au
lieu d'exiger & comme pour les fonctions... La solution ANSI me
semble plus uniforme.


En somme, ce que tu veux c'est d'étendre le défaut des tableaux à
des fonctions aussi.


Non, pas du tout. Je préfère l'uniformité, alors j'obligerais plutôt
&v[0]. Mais évidemment, c'est difficile étant donné la définition de
[] !


Certes. À un époque, je le croyais même universellement admis que les
tableau en C, c'était sérieusement cassé. La solution, évidemment, n'est
pas d'étendre l'erreur par ailleur, mais de la réparer. Il y en a même
eu des discussions à cet égard dans le comité C++, tout au début.

La motivation pour cette anomalie de comportement avec les tableaux
est due à l'histoire ; voir la spécification de B, et les documents
historiques à http://www.lysator.liu.se/c/. Mais c'est un défaut :
pourquoi est-ce que les tableaux fonctionnent différemment que les
autres types ?


Bien alors, j'aimerais l'uniformité avec les fonctions !


L'uniformité souhaitable serait que tous les types fonctionnent de la
même manière -- que ce soit un int, une classe, une table ou une
fonction. Pour des raisons historiques, les tables en C sont des types
éstrophiées. On a discuté la possibilité de corriger ce problème en
C++, mais le consensus était plutôt de l'ordre que c'était impossible
sans rompre complètement avec C, et que ce n'avait qu'un intérêt modéré
en C++, vue que de toute façon, on préfère des classes avec surcharge de
l'operator[] à des tables C. (C'était bien avant qu'on a proposé la STL
et std::vector, mais c'était plus ou moins accorder qu'on ne pouvait pas
promulguer une norme sans des classes de chaîne de caractères et des
tableaux dans la bibliothèque.)

--
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
Gabriel Dos Reis
"Michel Michaud" writes:

| >> En fait, si j'avais Ritchie devant moi, je lui demanderais
| >> pourquoi, dans son langage original, on peut écrire v pour
| >> &v[0] au lieu d'exiger & comme pour les fonctions... La
| >> solution ANSI me semble plus uniforme.
| >
| > ???
|
| Ton interrogation signifie quoi dans ce cas-ci ? Tu dois t'ennuyer
| un peu (ça me surprend) si tu veux qu'on essaie de deviner. Mais

non pas vraiment -- inventer de nouveaux outils pour C++ est un
travail a plein.

| bon, on peut jouer. Je vais supposer que tu ne comprends pas mon
| questionnement, mais évidemment tu me diras que ce n'est pas que
| tu voulais dire... Je reformule quand même et je pose une question
| sérieuse, qui m'intéresse. Pourquoi a-t-on besoin de la conversion
| implicite du nom d'un vecteur en adresse de son premier élément,
| plus que de la conversion du nom d'une fonction en adresse de
| cette fonction ?

Mais, on N'a PAS BESOIN de cette conversion. C'est une plaie qu'il
aurait fallu ne pas multiplier par un facteur plus grand que 1.

-- Gaby
2 3 4 5 6