web-dev-qa-db-fra.com

Pointeur de fonction typedef?

J'apprends à charger dynamiquement les DLL, mais ce que je ne comprends pas, c'est cette ligne.

typedef void (*FunctionFunc)();

J'ai quelques questions. Si quelqu'un peut y répondre, je vous en serais reconnaissant.

  1. Pourquoi typedef est-il utilisé?
  2. La syntaxe semble étrange; après void ne devrait-il pas y avoir un nom de fonction ou quelque chose? Cela ressemble à une fonction anonyme.
  3. Un pointeur de fonction est-il créé pour stocker l'adresse de mémoire d'une fonction?

Donc, je suis confus pour le moment; pouvez-vous clarifier les choses pour moi?

414
Jack Harvin

typedef est une construction de langage qui associe un nom à un type.
Vous l’utilisez de la même manière que vous utiliseriez le type original, par exemple

  typedef int myinteger;
  typedef char *mystring;
  typedef void (*myfunc)();

les utiliser comme

  myinteger i;   // is equivalent to    int i;
  mystring s;    // is the same as      char *s;
  myfunc f;      // compile equally as  void (*f)();

Comme vous pouvez le constater, vous pouvez simplement remplacer le nom typedefed par sa définition donnée ci-dessus.

La difficulté réside dans le pointeur sur la syntaxe et la lisibilité des fonctions en C et C++, et le typedef peut améliorer la lisibilité de telles déclarations. Cependant, la syntaxe est appropriée, car les fonctions - contrairement à d'autres types plus simples - peuvent avoir une valeur de retour et des paramètres, d'où la déclaration parfois longue et complexe d'un pointeur sur une fonction.

La lisibilité peut commencer à devenir vraiment délicate avec les pointeurs sur les tableaux de fonctions et quelques autres variantes encore plus indirectes.

Pour répondre à vos trois questions

  • Pourquoi typedef est-il utilisé? Pour faciliter la lecture du code - en particulier pour les pointeurs sur des fonctions ou les noms de structure.

  • La syntaxe a l'air bizarre (dans le pointeur sur la déclaration de fonction)) Cette syntaxe n'est pas évidente à lire, du moins au début. L'utilisation d'une déclaration typedef facilite la lecture

  • n pointeur de fonction est-il créé pour stocker l'adresse mémoire d'une fonction? Oui, un pointeur de fonction stocke l'adresse d'une fonction. Cela n'a rien à voir avec la construction typedef qui ne fait que faciliter l'écriture/la lecture d'un programme; le compilateur développe simplement la définition de typedef avant de compiler le code réel.

Exemple:

typedef int (*t_somefunc)(int,int);

int product(int u, int v) {
  return u*v;
}

t_somefunc afunc = &product;
...
int x2 = (*afunc)(123, 456); // call product() to calculate 123*456
429
Ring Ø
  1. typedef est utilisé pour alias les types; dans ce cas, vous aliasez FunctionFunc à void(*)().

  2. En effet, la syntaxe a l'air bizarre, regardez ceci:

    typedef   void      (*FunctionFunc)  ( );
    //         ^                ^         ^
    //     return type      type name  arguments
    
  3. Non, cela indique simplement au compilateur que le type FunctionFunc sera un pointeur de fonction, mais pas définir un, comme ceci:

    FunctionFunc x;
    void doSomething() { printf("Hello there\n"); }
    x = &doSomething;
    
    x(); //prints "Hello there"
    
177
Jacob Relkin

Sans le typedef Word, la déclaration déclarerait en C++ une variable FunctionFunc de type pointeur sur une fonction sans argument, renvoyant void.

Avec typedef, il définit plutôt FunctionFunc comme nom pour ce type.

31

Si vous pouvez utiliser C++ 11, vous voudrez peut-être utiliser les mots-clés std::function et using.

using FunctionFunc = std::function<void(int arg1, std::string arg2)>;
7
Halil Kaskavalci
#include <stdio.h>
#include <math.h>

/*
To define a new type name with typedef, follow these steps:
1. Write the statement as if a variable of the desired type were being declared.
2. Where the name of the declared variable would normally appear, substitute the new type name.
3. In front of everything, place the keyword typedef.
*/

// typedef a primitive data type
typedef double distance;

// typedef struct 
typedef struct{
    int x;
    int y;
} point;

//typedef an array 
typedef point points[100]; 

points ps = {0}; // ps is an array of 100 point 

// typedef a function
typedef distance (*distanceFun_p)(point,point) ; // TYPE_DEF distanceFun_p TO BE int (*distanceFun_p)(point,point)

// prototype a function     
distance findDistance(point, point);

int main(int argc, char const *argv[])
{
    // delcare a function pointer 
    distanceFun_p func_p;

    // initialize the function pointer with a function address
    func_p = findDistance;

    // initialize two point variables 
    point p1 = {0,0} , p2 = {1,1};

    // call the function through the pointer
    distance d = func_p(p1,p2);

    printf("the distance is %f\n", d );

    return 0;
}

distance findDistance(point p1, point p2)
{
distance xdiff =  p1.x - p2.x;
distance ydiff =  p1.y - p2.y;

return sqrt( (xdiff * xdiff) + (ydiff * ydiff) );
}
1
Amjad

Pour le cas général de la syntaxe, vous pouvez regarder annexe A de la norme ANSI C .

À partir de là, dans la forme Backus-Naur, vous pouvez voir que typedef a le type storage-class-specifier.

Dans le type declaration-specifiers, vous pouvez voir que vous pouvez mélanger plusieurs types de spécificateurs, dont l'ordre n'a pas d'importance.

Par exemple, il est correct de dire,

long typedef long a;

définir le type a comme alias pour long long. Donc, pour comprendre le typedef sur l'utilisation exhaustive, vous devez consulter une forme backus-naur qui définit la syntaxe (il existe de nombreuses grammaires correctes pour ANSI C, et pas seulement celle d'ISO).

Lorsque vous utilisez typedef pour définir un alias pour un type de fonction, vous devez le placer au même endroit que l'identificateur de la fonction. Dans votre cas, vous définissez le type FunctionFunc comme un alias pour un pointeur sur une fonction dont la vérification de type est désactivée à l'appel et ne renvoie rien.

1
alinsoar