2017-07-06 1 views
4

J'ai regardé mais je n'ai pas trouvé de référence directe pour cette question. Je suis nouveau à des pointeurs de fonction (et C), donc je ne connais pas tous les trucs qu'on peut faire encore :)Est-ce une façon correcte de passer une fonction dans une structure?

J'ai effectivement eu une fonction:

void select_comparator(My_Struct *structure, int (*comp)(int x, int y)) { 
    ... 

... où My_Struct a prototype:

typedef struct my_struct { 
    int (*comp)(int x, int y); 
} My_Struct; 

Modulo quelques petits détails. Je veux juste savoir si ce qui suit est la syntaxe correcte:

void select_comparator(My_Struct *structure, int (*comp)(int x, int y)) { 
    structure->comp = comp; 
} 

Il semble presque trop facile, et je suis inquiet qu'il est.

Répondre

3

Rien ne va pas: c'est la base des rappels dans . Assurez-vous simplement que la signature de votre pointeur de fonction correspond au type défini dans votre structure. Là où ça devient délicat à distance est quand vous utilisez ce dans un grand projet, et les gens oublient de vérifier si le pointeur de fonction est valide ou void, ainsi que des arguments, etc.

code


/******************************************************************************* 
* Preprocessor directives. 
******************************************************************************/ 
#include <stdio.h> 


/******************************************************************************* 
* Data types. 
******************************************************************************/ 
typedef struct my_struct { 
    int (*comp)(int x, int y); 
} My_Struct; 


/******************************************************************************* 
* Function prototypes. 
******************************************************************************/ 
int c(int a, int b); 
void select_comparator(My_Struct *structure, int (*comp)(int x, int y)); 


/******************************************************************************* 
* Function definitions. 
******************************************************************************/ 
/*----------------------------------------------------------------------------*/ 
int main(void) 
{ 
    My_Struct s; 

    select_comparator(&s, &c); 
    s.comp(1, 2); 

    return 0; 
} 

/*----------------------------------------------------------------------------*/ 
void select_comparator(My_Struct *structure, int (*comp)(int x, int y)) 
{ 
    structure->comp = comp; 
} 

/*----------------------------------------------------------------------------*/ 
int c(int a, int b) 
{ 
    int ret = 0; 
    if (a < b) { 
     ret = (-1); 
    } else if (a > b) { 
     ret = 1; 
    } 

    return ret; 
} 
+1

Merci pour l'astuce concernant les types de retour! En fait, cela va être pertinent, parce que je travaille sur un grand projet .... – Chris

1

Le code est correct.

Notez cependant que les pointeurs de fonction ont une syntaxe horrible en C, en particulier lorsqu'ils sont passés à des fonctions. Essayez d'écrire quelque chose comme "fonction retournant function-pointer et prenant function-pointer comme paramètre" et vous réaliserez rapidement que la syntaxe est pure folie.

Il est donc judicieux de faire en sorte que les pointeurs de fonction "tombent en ligne" avec le reste du langage en utilisant typedefs.

Code Vous pourriez être écrit comme ceci:

typedef int comp_t (int x, int y); // typedef a function type 

typedef struct { 
    comp_t* comp; // pointer to such a function type 
} My_Struct; 

void select_comparator(My_Struct *structure, comp_t* comp) { 
    structure->comp = comp; 
} 

Maintenant, le code tourne plus facile à lire et le pointeur de la fonction se comporte à peu près comme tout autre pointeur.

+1

Ils peuvent être décourageants, mais il n'y a pas de ** mauvais **. J'ai eu la chance de trouver [une très bonne explication de la "règle droite-gauche"] (http://ieng9.ucsd.edu/~cs30x/rt_lt.rule.html) au début de mes études «C», et il a rendu beaucoup de bizarreries de la langue plus faciles à suivre. – DevNull

+0

@DevNull Non, ils sont vraiment ** horribles. J'ai environ 20 ans d'expérience en C et encore ce n'est pas une tâche triviale même pour moi d'écrire quelque chose comme 'fonction prenant des paramètres ... renvoyant des paramètres de fonction-pointeur-à-fonction ...' (plus des qualificatifs en plus). Ecrire quelque chose comme ça sans typedef me prendra 10 minutes. L'écrire avec typedefs me prendra 10 secondes. La syntaxe ** est ** ce retardé, point. Il ne vaut même pas la peine de prendre le temps d'apprendre la syntaxe - c'est une connaissance inutile. Apprenez juste typedef, allez être productif, écrivez le code joli et lisible. – Lundin

+0

Je suis dans l'industrie depuis environ la même période et j'ai vécu une expérience très différente. La logique pour les interpréter, bien que désordonnée, est rigide et bien définie. Il est vrai que les typedefs ont leur place et facilitent le travail avec des pointeurs de fonction avec des équipes plus grandes. – DevNull