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
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
im letzten Beispiel würde sich ‘Quadrat’ nicht nur auf dasselbe beziehen, dh Zeiger auf die Funktion, anstatt &Quadrat zu verwenden.
– pranavk
5. März 2013 um 13:32 Uhr
Frage, in Ihrem ersten Typedef-Beispiel haben Sie das Formular typedef type alias aber bei Funktionszeigern scheint es nur 2 Argumente zu geben, typedef type. Wird als Alias standardmäßig der Name verwendet, der im Typargument angegeben ist?
– dchhetri
3. Mai 2013 um 3:56 Uhr
@pranavk: Ja, square und &square (und in der Tat, *square und **square) verweisen alle auf denselben Funktionszeiger.
– Jonathan Leffler
3. Mai 2013 um 3:58 Uhr
@ user814628: Es ist nicht ganz klar, was Sie fragen. Mit typedef int newnamedu machst newname in einen Alias für int. Mit typedef int (*func)(int)du machst func in einen Alias für int (*)(int) — ein Zeiger auf eine Funktion, die an nimmt int Argument und Rückgabe eines int Wert.
– Jonathan Leffler
3. Mai 2013 um 4:01 Uhr
Ich glaube, ich bin nur verwirrt wegen der Reihenfolge. Mit typedef int (*func)(int), verstehe ich, dass func ein Alias ist, nur ein wenig verwirrt, weil der Alias mit dem Typ verwickelt ist. Vorbeigehen typedef int INT Als Beispiel würde ich mich wohler fühlen, wenn der Typedef-Funktionszeiger die Form hätte typedef int(*function)(int) FUNC_1. Auf diese Weise kann ich den Typ und den Alias in zwei separaten Token sehen, anstatt sie zu einem zu vermaschen.
– dchhetri
3. Mai 2013 um 5:07 Uhr
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:
typedef tut nicht einen neuen Typ deklarieren. du kannst viele haben typedef-definierte Namen des gleichen Typs, und sie sind nicht eindeutig (zB bzgl. Überladen von Funktionen). Es gibt einige Umstände, unter denen Sie den Namen verwenden können, a typedef-definierter Name ist nicht genau gleichbedeutend mit dem, als was er definiert ist, sondern mehrfach typedef-definierte Namen für die gleichen, sind gleichwertig.
– Prost und hth. – Alf
28. November 2010 um 5:00 Uhr
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) );
}
Unter welchen Umständen wird das ‘&’ benötigt? Funktionieren zum Beispiel ‘func_p = &findDistance’ und ‘func_p = findDistance’ gleich gut?
– Donna
30. Oktober 2017 um 14:06 Uhr
Ein Funktionsname ist ein Zeiger, daher müssen Sie kein ‘&’ damit verwenden. Mit anderen Worten, ‘&’ ist optional, wenn Funktionszeiger berücksichtigt werden. Für primitive Datentypen müssen Sie jedoch das ‘&’ verwenden, um seine Adresse zu erhalten.
– Amjad
30. Oktober 2017 um 16:41 Uhr
Es ist einfach immer seltsam aufgefallen, dass das ‘&’ jemals optional sein kann. Wenn eine Typedef verwendet wird, um einen Zeiger auf ein Primitiv zu erstellen (z typedef (*double) pist das ‘&’ optional?
– Donna
31. Oktober 2017 um 17:39 Uhr
Ich glaube, du wolltest tippen typedef double* p um einen Zeiger auf ein Double zu definieren. Wenn Sie die füllen möchten p Zeiger von einer primitiven Variablen, müssen Sie das ‘&’ verwenden. Eine Randbemerkung: Wir verwenden *, um einen Zeiger zu dereferenzieren. Die * wird im Funktionszeiger verwendet, um den Zeiger (Funktionsname) zu dereferenzieren und zu dem Speicherblock zu gehen, in dem sich die Funktionsanweisungen befinden.
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.
Unter welchen Umständen wird das ‘&’ benötigt? Funktionieren zum Beispiel ‘func_p = &findDistance’ und ‘func_p = findDistance’ gleich gut?
– Donna
30. Oktober 2017 um 14:06 Uhr
Ein Funktionsname ist ein Zeiger, daher müssen Sie kein ‘&’ damit verwenden. Mit anderen Worten, ‘&’ ist optional, wenn Funktionszeiger berücksichtigt werden. Für primitive Datentypen müssen Sie jedoch das ‘&’ verwenden, um seine Adresse zu erhalten.
– Amjad
30. Oktober 2017 um 16:41 Uhr
Es ist einfach immer seltsam aufgefallen, dass das ‘&’ jemals optional sein kann. Wenn eine Typedef verwendet wird, um einen Zeiger auf ein Primitiv zu erstellen (z typedef (*double) pist das ‘&’ optional?
– Donna
31. Oktober 2017 um 17:39 Uhr
Ich glaube, du wolltest tippen typedef double* p um einen Zeiger auf ein Double zu definieren. Wenn Sie die füllen möchten p Zeiger von einer primitiven Variablen, müssen Sie das ‘&’ verwenden. Eine Randbemerkung: Wir verwenden *, um einen Zeiger zu dereferenzieren. Die * wird im Funktionszeiger verwendet, um den Zeiger (Funktionsname) zu dereferenzieren und zu dem Speicherblock zu gehen, in dem sich die Funktionsanweisungen befinden.
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