
JackHarvin
Ich lerne, wie man DLLs dynamisch lädt, aber was ich nicht verstehe, ist diese Zeile
typedef void (*FunctionFunc)();
Ich habe ein paar Fragen. Wenn jemand sie beantworten kann, wäre ich dankbar.
- Warum ist
typedef
benutzt?
- Die Syntax sieht seltsam aus; nach dem
void
sollte da nicht ein funktionsname oder so stehen? Es sieht aus wie eine anonyme Funktion.
- Wird ein Funktionszeiger erstellt, um die Speicheradresse einer Funktion zu speichern?
Also bin ich im Moment verwirrt; kannst du mir dinge erklären?

Déjà-vu
typedef
ist ein Sprachkonstrukt, das einem Typ einen Namen zuordnet.
Sie verwenden es genauso, wie Sie beispielsweise den ursprünglichen Typ verwenden würden
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 die einfach ersetzen typdefiniert Name mit seiner oben angegebenen Definition.
Die Schwierigkeit liegt in der Syntax und Lesbarkeit der Zeiger auf Funktionen in C und C++, und die typedef
kann die Lesbarkeit solcher Erklärungen 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 Varianten sehr schwierig werden.
Um deine drei Fragen zu beantworten
-
Warum wird typedef verwendet?
Um das Lesen des Codes zu erleichtern – insbesondere für Zeiger auf Funktionen oder Strukturnamen.
-
Die Syntax sieht seltsam aus (im Zeiger auf die Funktionsdeklaration)
Diese Syntax ist zumindest am Anfang nicht offensichtlich zu lesen. Verwendung einer typedef
Deklaration erleichtert stattdessen das Lesen
-
Wird ein Funktionszeiger erstellt, um die Speicheradresse einer Funktion zu speichern?
Ja, ein Funktionszeiger speichert die Adresse einer Funktion. Das hat nichts mit dem zu tun typedef
Konstrukt, das nur das Schreiben/Lesen eines Programms erleichtert ; Der Compiler erweitert lediglich die Typedef-Definition, bevor er den eigentlichen Code kompiliert.
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

Jakob Relk
-
typedef
wird verwendet, um Typen zu aliasieren; in diesem Fall aliasing Sie FunctionFunc
zu void(*)()
.
-
In der Tat sieht die Syntax seltsam aus, schau dir das an:
typedef void (*FunctionFunc) ( );
// ^ ^ ^
// return type type name arguments
-
Nein, das sagt dem Compiler einfach, dass die FunctionFunc
type wird ein Funktionszeiger sein, ist es nicht definieren eins, so:
FunctionFunc x;
void doSomething() { printf("Hello there\n"); }
x = &doSomething;
x(); //prints "Hello there"

Prost und hth. – Alf
Ohne das typedef
Word, in C++ würde die Deklaration eine Variable deklarieren FunctionFunc
vom Typ Zeiger auf Funktion ohne Argumente, Rückgabe void
.
Mit dem typedef
es definiert stattdessen FunctionFunc
als Name für diesen Typ.
Wenn Sie C++11 verwenden können, möchten Sie vielleicht verwenden std::function
und using
Stichwort.
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 können Sie nachsehen Anhang A des ANSI-C-Standards.
In der Backus-Naur-Form von dort sieht man das typedef
hat den Typ storage-class-specifier
.
Im Typ declaration-specifiers
Sie können sehen, dass Sie viele Spezifizierertypen mischen können, deren Reihenfolge keine Rolle spielt.
Richtig ist zum Beispiel zu sagen,
long typedef long a;
um den Typ zu definieren a
als Pseudonym für long long
. Um also die Typedef bei der erschöpfenden Verwendung zu verstehen, müssen Sie ein Backus-Naur-Formular konsultieren, das die Syntax definiert (es gibt viele korrekte Grammatiken für ANSI C, nicht nur die von ISO).
Wenn Sie typedef verwenden, um einen Alias für einen Funktionstyp zu 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.
9965000cookie-checkTypedef-Funktionszeiger?yes
Schauen Sie sich den Link an (letzter Abschnitt) learncpp.com/cpp-tutorial/78-function-pointers
– begeisterter Geek
3. Mai 2013 um 3:28 Uhr
Zu beachten ist, dass seit c++11
using FunctionFunc = void (*)();
kann stattdessen verwendet werden. Es ist etwas klarer, dass Sie nur einen Namen für einen Typ (Zeiger auf eine Funktion) deklarieren.– Benutzer362515
8. Januar 2016 um 11:55 Uhr
nur um @ user362515 hinzuzufügen, eine etwas klarere Form für mich ist:
using FunctionFunc = void(void);
– Topspin
28. Mai 2016 um 21:15 Uhr
@topspin IIRC diese beiden sind nicht gleich. Einer ist ein Funktionszeigertyp, der andere ist ein Funktionstyp. Es gibt eine implizite Konvertierung, deshalb funktioniert es, IANA(C++)L, also kann man eingreifen und mich korrigieren. Auf jeden Fall, wenn die Absicht ist, einen Zeigertyp zu definieren, denke ich, dass die Syntax mit der
*
ist etwas deutlicher.– Benutzer362515
31. Mai 2016 um 18:11 Uhr
Hier ist eine verwandte Frage, die ich vor langer Zeit gestellt habe, warum beides
myFuncPtr()
und(*myFuncPtr)()
beides gültige Funktionsaufrufe sind.– Gabriel Staples
5. Februar um 2:01 Uhr