Typedef-Funktionszeiger?

Lesezeit: 8 Minuten

Typedef Funktionszeiger
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.

  1. Warum ist typedef benutzt?
  2. Die Syntax sieht seltsam aus; nach dem void sollte da nicht ein funktionsname oder so stehen? Es sieht aus wie eine anonyme Funktion.
  3. Wird ein Funktionszeiger erstellt, um die Speicheradresse einer Funktion zu speichern?

Also bin ich im Moment verwirrt; kannst du mir dinge erklären?

  • 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

1647158414 910 Typedef Funktionszeiger
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

1647158415 434 Typedef Funktionszeiger
Jakob Relk

  1. typedef wird verwendet, um Typen zu aliasieren; in diesem Fall aliasing Sie FunctionFunc zu void(*)().

  2. In der Tat sieht die Syntax seltsam aus, schau dir das an:

    typedef   void      (*FunctionFunc)  ( );
    //         ^                ^         ^
    //     return type      type name  arguments
    
  3. 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"
    

  • 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


Typedef Funktionszeiger
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.

    – Amjad

    31. Oktober 2017 um 20:16 Uhr

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.

  • 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.

    – Amjad

    31. Oktober 2017 um 20:16 Uhr

996500cookie-checkTypedef-Funktionszeiger?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy