it-swarm.com.de

Typedef Funktionszeiger?

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.

  1. Warum wird typedef verwendet?
  2. Die Syntax sieht merkwürdig aus. nach void sollte es keinen Funktionsnamen geben oder so? Es sieht aus wie eine anonyme Funktion.
  3. Wird ein Funktionszeiger erstellt, um die Speicheradresse einer Funktion zu speichern?

Ich bin also im Moment verwirrt. Kannst du mir die Dinge erklären?

414
Jack Harvin

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
429
Ring Ø
  1. typedef wird für Alias-Typen verwendet. In diesem Fall veränderst du FunctionFunc auf void(*)().

  2. Tatsächlich sieht die Syntax merkwürdig aus, sehen Sie sich das an:

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

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.

31

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)>;
7
#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) );
}
1
Amjad

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.

1
alinsoar