Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Copie en mémoire d'une fonction (pointeur)

16 réponses
Avatar
Okerampa
Bonjour.
Je veux utiliser des pointeurs de fonction:

ptrFunc (*func)(int);

ptrFunc tabFunc[N];
tabFunc[0]=3D&somme;
tabFunc[1]=3D&somme;

etc.

Mais je veux que somme garde une variable en m=E9moire, donc j'utilise
un type static
ex (vraiment juste pour l'exemple):
somme(int i)
{
static z=3D0;
z+=3Di;
}

Cependant je veux que ces variables statiques soient diff=E9rentes pour
toutes mes fonctions de tabFunc.
Ai-je le droit de faire quelque chose du genre

ptrFunc *fonction=3D(ptrFunc*)malloc(sizeof(*somme));
memcpy(fonction,somme,sizeof(somme));
tabFunc[1]=3Dfonction;

?

Merci (je n'ai pas test=E9 j'aimerais surtout savoir si il y a une
erreur dans mon raisonnement qui me parait correct, et je n'ai rien
trouv=E9 l=E0 dessus encore sur le net)

10 réponses

1 2
Avatar
Marc Boyer
Okerampa wrote:
Je veux utiliser des pointeurs de fonction:

ptrFunc (*func)(int);

ptrFunc tabFunc[N];
tabFunc[0]=&somme;
tabFunc[1]=&somme;

etc.

Mais je veux que somme garde une variable en mémoire, donc j'utilise
un type static
ex (vraiment juste pour l'exemple):
somme(int i)
{
static z=0;
z+=i;
}

Cependant je veux que ces variables statiques soient différentes pour
toutes mes fonctions de tabFunc.
Ai-je le droit de faire quelque chose du genre

ptrFunc *fonction=(ptrFunc*)malloc(sizeof(*somme));
memcpy(fonction,somme,sizeof(somme));
tabFunc[1]=fonction;


Ca me semble très douteux. D'ailleurs, je parie que ton
compilateur va te jetter.

Merci (je n'ai pas testé j'aimerais surtout savoir si il y a une
erreur dans mon raisonnement qui me parait correct, et je n'ai rien
trouvé là dessus encore sur le net)


Ben, il est difficile de faire de la doc sur tout ce qui est
impossible.
Mais sachant que dans de nombreux OS, données et codesont dans
des espaces mémoires distints, je ne pense pas que la norme
oblige les compilateurs a permettre des choses aussi étrages...


Marc Boyer
--
Je ne respecte plus le code de la route à vélo depuis une double fracture
due au fait que j'étais le seul à le respecter.

Avatar
Laurent Deniau
Okerampa wrote:
Bonjour.
Je veux utiliser des pointeurs de fonction:

ptrFunc (*func)(int);

ptrFunc tabFunc[N];
tabFunc[0]=&somme;
tabFunc[1]=&somme;

etc.

Mais je veux que somme garde une variable en mémoire, donc j'utilise
un type static
ex (vraiment juste pour l'exemple):
somme(int i)
{
static z=0;
z+=i;
}

Cependant je veux que ces variables statiques soient différentes pour
toutes mes fonctions de tabFunc.
Ai-je le droit de faire quelque chose du genre

ptrFunc *fonction=(ptrFunc*)malloc(sizeof(*somme));
memcpy(fonction,somme,sizeof(somme));
tabFunc[1]=fonction;

?

Merci (je n'ai pas testé j'aimerais surtout savoir si il y a une
erreur dans mon raisonnement qui me parait correct, et je n'ai rien
trouvé là dessus encore sur le net)


Ce que tu essayes de faire s'appelle une fermeture. C'est a dire une
fonction plus un contexte. Ce n'est pas possible directement en C, mais
on peut facilement le simuler avec une tres bonne efficacite.

a+, ld.

Avatar
Okerampa
Merci. Par simuler entendez-vous que je dois simuler le changement de
contexte que je souhaite en mettant moi même des variables directement
sur la pile?
Avatar
Christophe Blaess
Je veux utiliser des pointeurs de fonction:

ptrFunc (*func)(int);

ptrFunc tabFunc[N];
tabFunc[0]=&somme;
tabFunc[1]=&somme;

etc.

Mais je veux que somme garde une variable en mémoire, donc j'utilise
un type static
ex (vraiment juste pour l'exemple):
somme(int i)
{
static z=0;
z+=i;
}



S'agit-il obligatoirement d'une variable statique, ou peut-on
ajouter un argument à la fonction ? Dans le second cas on pourrait
imaginer quelque chose comme :

typedef struct {
ptrFunc fctn;
int data;
} fonction_t;

fonction_t tabFunc[N];

que l'on initialise avec des :


tabFunc[0].fctn = somme;
tabFunc[0].data = 1;

La fonction doit être réécrite avec un argument supplémentaire :

void somme(int i, int * privee)
{
*privee += i;
}

et l'invocation se fait ainsi :

tabFunc[i].fct(argument, & (tabFunc[i].data));

On peut la simplifier en passant par une macro :

#define FONCTION(i,arg) tabFunc[i].fct(arg,&(tabFunc[i].data))


--
Christophe Blaess
http://www.blaess.fr/christophe/

Avatar
Laurent Deniau
Okerampa wrote:
Merci. Par simuler entendez-vous que je dois simuler le changement de
contexte que je souhaite en mettant moi même des variables directement
sur la pile?


Non, en la passant explicitement ou implicitement comme argument.

cf l'exemple de C.B. comme point de depart. Le fait est que si c'est
seulement une variable locale statique dont tu as besoin, le probleme
est nettement plus simple que de simuler une fermeture.

a+, ld.

Avatar
Okerampa
Laurent Deniau wrote:
Okerampa wrote:

Merci. Par simuler entendez-vous que je dois simuler le changement de
contexte que je souhaite en mettant moi même des variables directement
sur la pile?



Non, en la passant explicitement ou implicitement comme argument.

Au temps pour moi j'ai écrit sans réfléchir :( J'avais peur d'avoir à

écrire un vecteur de static en mémoire je cherchais donc autre chose.

cf l'exemple de C.B. comme point de depart. Le fait est que si c'est
seulement une variable locale statique dont tu as besoin, le probleme
est nettement plus simple que de simuler une fermeture.


Oui j'aime bien l'exemple de C.B. Ca me conviendra bien :) Je me
souviens maintenant que j'avais déjà vu ce genre de code quand on
parlait de faire du C++ avec du C (fonctions dans des structs)...
Merci beaucoup.

a+, ld.




Avatar
Okerampa
Christophe Blaess wrote:

S'agit-il obligatoirement d'une variable statique, ou peut-on
ajouter un argument à la fonction ? Dans le second cas on pourrait
imaginer quelque chose comme :

typedef struct {
ptrFunc fctn;
int data;
} fonction_t;

fonction_t tabFunc[N];

que l'on initialise avec des :


tabFunc[0].fctn = somme;
tabFunc[0].data = 1;

La fonction doit être réécrite avec un argument supplémentaire :

void somme(int i, int * privee)
{
*privee += i;
}

et l'invocation se fait ainsi :

tabFunc[i].fct(argument, & (tabFunc[i].data));

On peut la simplifier en passant par une macro :

#define FONCTION(i,arg) tabFunc[i].fct(arg,&(tabFunc[i].data))




Merci beaucoup j'utiliserai quelque chose dans le genre.

Avatar
Okerampa
Ai-je le droit de faire quelque chose du genre

ptrFunc *fonction=(ptrFunc*)malloc(sizeof(*somme));
memcpy(fonction,somme,sizeof(somme));
tabFunc[1]=fonction;


Ca me semble très douteux. D'ailleurs, je parie que ton
compilateur va te jetter.


Oui, "ISO C++ interdit l'application de sizeof à une expression d'un
type fonction" sur le sizeof
Je pourrais retenter en compilant explicitement du C pour voir le
message d'erreur... (je sais c'est pas très propre ce que je fais mais
je suis obligé d'utiliser un peu de C++ pour ma version actuelle...)

Merci (je n'ai pas testé j'aimerais surtout savoir si il y a une
erreur dans mon raisonnement qui me parait correct, et je n'ai rien
trouvé là dessus encore sur le net)


Ben, il est difficile de faire de la doc sur tout ce qui est
impossible.
Mais sachant que dans de nombreux OS, données et codesont dans
des espaces mémoires distints, je ne pense pas que la norme
oblige les compilateurs a permettre des choses aussi étrages...



C'est vrai mais un compilateur pourrait s'arranger pour que ça marche
(un peu comme une fonction inline, et _inline existe bien en C, de la
il ne resterait qu'à allouer du static).


Avatar
Marc Boyer
Okerampa a écrit :
Ai-je le droit de faire quelque chose du genre

ptrFunc *fonction=(ptrFunc*)malloc(sizeof(*somme));
memcpy(fonction,somme,sizeof(somme));
tabFunc[1]=fonction;


Ca me semble très douteux. D'ailleurs, je parie que ton
compilateur va te jetter.


Oui, "ISO C++ interdit l'application de sizeof à une expression d'un
type fonction" sur le sizeof
Je pourrais retenter en compilant explicitement du C pour voir le
message d'erreur... (je sais c'est pas très propre ce que je fais mais
je suis obligé d'utiliser un peu de C++ pour ma version actuelle...)


Je pense que ça fera pas grande différence.

Merci (je n'ai pas testé j'aimerais surtout savoir si il y a une
erreur dans mon raisonnement qui me parait correct, et je n'ai rien
trouvé là dessus encore sur le net)


Ben, il est difficile de faire de la doc sur tout ce qui est
impossible.
Mais sachant que dans de nombreux OS, données et codesont dans
des espaces mémoires distints, je ne pense pas que la norme
oblige les compilateurs a permettre des choses aussi étrages...


C'est vrai mais un compilateur pourrait s'arranger pour que ça marche
(un peu comme une fonction inline, et _inline existe bien en C, de la
il ne resterait qu'à allouer du static).


S'arranger pour que ça marche ? J'ai peur que ça implique
une modif du linkage entre modules, et ça, même C++ ne
s'y est pas risqué.

Pour allouer une telle fonction, il faut que sizeof
retourne la taille des var statiques. OK.
Ensuite, pour accéder à une telle fonction par
un pointeur de fonction, sur quel code pointe-on ?
Surement pas sur le code original, puisqu'il ne sait
pas avec quelles variables travailler. Pour dire au code
avec quelle va travailler, il faut lui donner une info
en plus. Ou la stocker ? Comment lui faire passer ?
Alors qu'il est tellement simple à l'utilisateur de
faire une fonction avec un parametre de plus...

Marc Boyer
--
Je ne respecte plus le code de la route à vélo depuis une double fracture
due au fait que j'étais le seul à le respecter.



Avatar
Okerampa
Ok je suis peut être ignorant, mais une variable static est quelque
part en ram? Enfin en tout cas dans la mémoire heap.
De là, il est entièrement possible de créer un code assembleur de la
fonction copié (la même, mais copiée, comme on copie en C++ avec un
constructeur par recopie), mais de prendre pour variable static aussi
des copies des variables? D'où ma question sur le _inline qui est a ma
connaissance une copie du code de la fonction.

Parce que je n'ai pas testé, mais je suppose que deux pointeurs de
fonction qui pointent sur la même fonction partagent le static (je ne
me trompe pas, là?)

Finalement j'ai pris la solution de passer en argument, mais imaginons
que je mette un compteur dans ma fonction, je suis obligé d'utiliser
cette ruse de passage par argument.
1 2