C: Comment puis-je utiliser un tableau de pointeur à fonction unique pour les fonctions avec un nombre de parameters variable?

La question dit à peu près tout.

Je ne suis pas sûr de savoir comment faire cela et je n’ai jamais approché quoi que ce soit qui fonctionne.

Voici quelques exemples de fonctions:

add(int x, int y) { return x+y; } 

et,

 mean(int x1, int y1, int x2, int y2) { return (x1 + y1 + x2 + y2) / 4; } 

Jusqu’à présent, j’ai essayé d’utiliser typedef avec les deux, mais je ne vois pas comment faire en sorte que quelque chose pointe vers l’un ou l’autre type:

 typedef int (*mathfunc2)(int x, int y); typedef int (*mathfunc4)(int x1, int y1, int x2, int y2); ????? func_table[2] = {add, mean}; 

Vous devez choisir un type de pointeur de fonction à utiliser comme “pointeur de fonction générique”, utiliser ce type pour définir votre tableau et utiliser des conversions explicites. La conversion d’un type de pointeur de fonction à un autre, puis de nouveau, garantit la préservation de la valeur.

En d’autres termes:

 typedef int (*generic_fp)(void); generic_fp func_table[2] = { (generic_fp)add, (generic_fp)mean }; 

Ensuite, pour appeler add , vous devez le redéfinir:

 result = ((mathfunc2)func_table[0])(x, y); 

Vous pouvez définir des macros si vous le trouvez plus acceptable:

 #define FUNC_2(f, p1, p2) ((mathfunc2)(f))(p1, p2) #define FUNC_4(f, p1, p2, p3, p4) ((mathfunc4)(f))(p1, p2, p3, p4) result = FUNC_2(func_table[0], x, y); 

Vous pouvez utiliser le motif de façade comme ceci:

 int add(int x, int y); int mean(int x1, int y1, int x2, int y2); typedef int (*operation_fp)(int argc, int* argv); int add_wrapper(int argc, int* argv) { return add(argv[0], argv[1]); } int mean_wrapper(int argc, int* argv) { return mean(argv[0], argv[1], argv[2], argv[3]); } operation_fp func_table[2] = { add_wrapper, mean_wrapper }; 

Bien que le code soit moche, il fait le travail. Vous devez append une logique de validation dans les wrappers.

 int (*func[])() = { add, mean }; 

Ces deux types de fonctions sont incompatibles. Ssortingctement parlant, ils pourraient être mis en œuvre en utilisant des arguments de transmission complètement différents. Une implémentation peut choisir, par exemple, que toutes les fonctions comportant jusqu’à 3 parameters les reçoivent via des registres et que toutes les autres fonctions les reçoivent via la stack.

Cependant, vous pouvez définir les deux fonctions avec des parameters varargs pour qu’elles suivent le même schéma de passage de parameters.

De toute façon, comment aviez-vous l’intention d’appeler ces fonctions sans savoir combien de parameters elles attendaient?