J'apprends à charger dynamiquement des DLL mais ce que je ne comprends pas c'est cette ligne
typedef void (*FunctionFunc)();
J'ai quelques questions. Si quelqu'un est en mesure de leur répondre, je vous en serais reconnaissant.
- Pourquoi est-il
typedef
utilisé? - La syntaxe semble étrange; après
void
ne devrait-il pas y avoir de nom de fonction ou quelque chose? Cela ressemble à une fonction anonyme. - Un pointeur de fonction est-il créé pour stocker l'adresse mémoire d'une fonction?
Je suis donc confus en ce moment; pouvez-vous clarifier les choses pour moi?
using FunctionFunc = void (*)();
peut être utilisé à la place. Il est un peu plus clair que voususing FunctionFunc = void(void);
*
est un peu plus explicite.Réponses:
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 d'origine, par exemple
les utiliser comme
Comme vous pouvez le voir, vous pouvez simplement remplacer le nom typé par sa définition donnée ci-dessus.
La difficulté réside dans le pointeur vers la syntaxe des fonctions et la lisibilité en C et C ++, et
typedef
peut améliorer la lisibilité de ces 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 vers la fonction.La lisibilité peut commencer à être vraiment délicate avec des pointeurs vers des tableaux de fonctions, et quelques autres saveurs 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 vers des fonctions ou des noms de structure.
La syntaxe semble étrange (dans le pointeur vers la déclaration de fonction) Cette syntaxe n'est pas évidente à lire, du moins au début. L'utilisation d'une
typedef
déclaration facilite la lectureUn 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
typedef
construction qui facilite seulement l'écriture / lecture d'un programme; le compilateur développe simplement la définition de typedef avant de compiler le code réel.Exemple:
la source
typedef type alias
mais avec des pointeurs de fonction , il semble seulement être 2 arguments,typedef type
. L'alias a-t-il par défaut le nom spécifié dans l'argument type?square
et&square
(et, en effet,*square
et**square
) font tous référence au même pointeur de fonction.typedef int newname
, vous deveneznewname
un alias pourint
. Avectypedef int (*func)(int)
, vous transformezfunc
en un alias pourint (*)(int)
- un pointeur pour fonctionner en prenant unint
argument et en retournant uneint
valeur.int (*func)(int)
, je comprends que func est un alias, juste un peu confus car l'alias est enchevêtré avec le type. En passant partypedef int INT
l'exemple, je serais plus à l'aise si le pointeur de la fonction typedef était de formetypedef int(*function)(int) FUNC_1
. De cette façon, je peux voir le type et l'alias dans deux jetons distincts au lieu d'être maillés en un seul.typedef
est utilisé pour alias les types; dans ce cas , vous êtes aliasingFunctionFunc
àvoid(*)()
.En effet, la syntaxe semble étrange, jetez un œil à ceci:
Non, cela indique simplement au compilateur que le
FunctionFunc
type sera un pointeur de fonction, il n'en définit pas un, comme ceci:la source
typedef
ne déclare pas un nouveau type. vous pouvez avoir plusieurstypedef
noms définis par le même type, et ils ne sont pas distincts (par exemple wrt. surcharge des fonctions). il y a des circonstances dans lesquelles, en ce qui concerne la façon dont vous pouvez utiliser le nom, untypedef
nom -defined n'est pas exactement équivalent à ce qu'il est défini, mais plusieurstypedef
noms -defined pour le même, sont équivalents.Sans le
typedef
mot, en C ++, la déclaration déclarerait une variableFunctionFunc
de type pointeur pour fonctionner sans argument, en retournantvoid
.Avec le
typedef
il définit à la placeFunctionFunc
comme un nom pour ce type.la source
Si vous pouvez utiliser C ++ 11, vous voudrez peut-être utiliser le mot
std::function
-using
clé et .la source
using
mot clé C ++ 11 seraittypedef std::function<void(int, std::string)> FunctionFunc;
, juste au cas où quelqu'un voudrait un autre wrapper autour des fonctions sans C ++ 11la source
typedef (*double) p
-à- d. , Le '&' est-il facultatif?typedef double* p
pour définir un pointeur sur un double. Si vous souhaitez remplir lep
pointeur à partir d'une variable primitive, vous devrez utiliser le '&'. Une note latérale, nous vous * * nom du pointeur> pour déréférencer un pointeur. Le*
est utilisé dans le pointeur de fonction pour déréférencer le pointeur (nom de la fonction) et aller au bloc de mémoire où se trouvent les instructions de fonction.Pour le cas général de la syntaxe , vous pouvez consulter l' annexe A de la norme ANSI C .
Dans la forme Backus-Naur à partir de là, vous pouvez voir qui
typedef
a le typestorage-class-specifier
.Dans le type,
declaration-specifiers
vous pouvez voir que vous pouvez mélanger de nombreux types de spécificateurs, dont l'ordre n'a pas d'importance.Par exemple, il est correct de dire:
pour définir le type
a
comme alias pourlong long
. Donc, pour comprendre le typedef sur l'utilisation exhaustive dont vous avez besoin, consultez une forme backus-naur qui définit la syntaxe (il existe de nombreuses grammaires correctes pour ANSI C, pas seulement celle d'ISO).Lorsque vous utilisez typedef pour définir un alias pour un type de fonction, vous devez placer l'alias au même endroit où vous placez l'identifiant de la fonction. Dans votre cas, vous définissez le type
FunctionFunc
comme un alias pour qu'un pointeur fonctionne, dont la vérification de type est désactivée à l'appel et ne renvoie rien.la source