Ich lerne, wie man DLLs dynamisch lädt, aber ich verstehe diese Zeile nicht
typedef void (*FunctionFunc)();
Ich habe ein paar Fragen. Wenn jemand antworten kann, wäre ich dankbar.
typedef
verwendet?void
sollte es keinen Funktionsnamen geben oder so? Es sieht aus wie eine anonyme Funktion.Ich bin also im Moment verwirrt. Kannst du mir die Dinge erklären?
typedef
ist ein Sprachkonstrukt, das einem Typ einen Namen zuordnet.
Sie verwenden es genauso wie beispielsweise den Originaltyp
typedef int myinteger;
typedef char *mystring;
typedef void (*myfunc)();
mit ihnen wie
myinteger i; // is equivalent to int i;
mystring s; // is the same as char *s;
myfunc f; // compile equally as void (*f)();
Wie Sie sehen können, können Sie einfach den typisierten Namen durch die oben angegebene Definition ersetzen.
Die Schwierigkeit liegt im Zeiger auf die Funktionssyntax und die Lesbarkeit in C und C++, und typedef
kann die Lesbarkeit solcher Deklarationen verbessern. Die Syntax ist jedoch angemessen, da Funktionen - im Gegensatz zu anderen einfacheren Typen - einen Rückgabewert und Parameter haben können, also die manchmal langwierige und komplexe Deklaration eines Zeigers auf eine Funktion.
Die Lesbarkeit kann bei Zeigern auf Funktions-Arrays und einigen anderen, noch indirekteren Aromen sehr schwierig werden.
Um Ihre drei Fragen zu beantworten
Warum wird typedef verwendet? Zum leichteren Lesen des Codes - insbesondere für Zeiger auf Funktionen oder Strukturnamen.
Die Syntax sieht merkwürdig aus (im Zeiger auf die Funktionsdeklaration) Diese Syntax ist zumindest zu Beginn nicht offensichtlich zu lesen. Die Verwendung einer typedef
-Deklaration erleichtert stattdessen das Lesen
Wird ein Funktionszeiger zum Speichern der Speicheradresse einer Funktion erstellt? Ja, ein Funktionszeiger speichert die Adresse einer Funktion. Dies hat nichts mit dem Konstrukt typedef
zu tun, das nur das Schreiben/Lesen eines Programms erleichtert. Der Compiler erweitert lediglich die Typedef-Definition, bevor der eigentliche Code kompiliert wird.
Beispiel:
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
wird für Alias-Typen verwendet. In diesem Fall veränderst du FunctionFunc
auf void(*)()
.
Tatsächlich sieht die Syntax merkwürdig aus, sehen Sie sich das an:
typedef void (*FunctionFunc) ( );
// ^ ^ ^
// return type type name arguments
Nein, dies sagt dem Compiler einfach, dass der FunctionFunc
-Typ ein Funktionszeiger sein wird, nicht define one, wie folgt:
FunctionFunc x;
void doSomething() { printf("Hello there\n"); }
x = &doSomething;
x(); //prints "Hello there"
Ohne das Wort typedef
würde die Deklaration in C++ eine Variable FunctionFunc
vom Typ Zeiger auf Funktion ohne Argumente deklarieren und void
zurückgeben.
Bei typedef
wird stattdessen FunctionFunc
als Name für diesen Typ definiert.
Wenn Sie C++ 11 verwenden können, möchten Sie möglicherweise das Schlüsselwort std::function
und using
verwenden.
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) );
}
Für den allgemeinen Fall der Syntax sehen Sie sich Anhang A des ANSI C-Standards an.
In der Backus-Naur-Form von dort können Sie sehen, dass typedef
den Typ storage-class-specifier
hat.
Im Typ declaration-specifiers
können Sie sehen, dass Sie viele Spezifizierertypen mischen können, deren Reihenfolge keine Rolle spielt.
Zum Beispiel ist es richtig zu sagen,
long typedef long a;
um den Typ a
als Alias für long long
zu definieren. Um den Typedef für die erschöpfende Verwendung zu verstehen, müssen Sie eine Backus-Naur-Form konsultieren, die die Syntax definiert (es gibt viele korrekte Grammatiken für ANSI C, nicht nur die von ISO).
Wenn Sie mit typedef einen Alias für einen Funktionstyp definieren, müssen Sie den Alias an derselben Stelle platzieren, an der Sie den Bezeichner der Funktion platzieren. In Ihrem Fall definieren Sie den Typ FunctionFunc
als Alias für einen Zeiger auf eine Funktion, deren Typprüfung beim Aufruf deaktiviert ist und nichts zurückgibt.