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.
typedef
est-il utilisé?void
ne devrait-il pas y avoir un nom de fonction ou quelque chose? Cela ressemble à une fonction anonyme.Donc, je suis confus pour le moment; pouvez-vous clarifier les choses pour moi?
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
typedef
est utilisé pour alias les types; dans ce cas, vous aliasez FunctionFunc
à void(*)()
.
En effet, la syntaxe a l'air bizarre, regardez ceci:
typedef void (*FunctionFunc) ( );
// ^ ^ ^
// return type type name arguments
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"
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.
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)>;
#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) );
}
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.