Typedef-functieaanwijzer?

Ik ben aan het leren hoe ik DLL’s dynamisch kan laden, maar wat ik niet begrijp is deze regel

typedef void (*FunctionFunc)();

Ik heb een paar vragen. Als iemand ze kan beantwoorden, zou ik dankbaar zijn.

  1. Waarom wordt typedefgebruikt?
  2. De syntaxis ziet er vreemd uit; zou er na voidgeen functienaam moeten staan of zo? Het ziet eruit als een anonieme functie.
  3. Is er een functieaanwijzer gemaakt om het geheugenadres van een functie op te slaan?

Dus ik ben op dit moment in de war; kun je dingen voor me verduidelijken?


Antwoord 1, autoriteit 100%

typedefis een taalconstructie die een naam aan een type koppelt.
U gebruikt het op dezelfde manier als u het originele type zou gebruiken, bijvoorbeeld

 typedef int myinteger;
  typedef char *mystring;
  typedef void (*myfunc)();

ze gebruiken zoals

 myinteger i;   // is equivalent to    int i;
  mystring s;    // is the same as      char *s;
  myfunc f;      // compile equally as  void (*f)();

Zoals u kunt zien, kunt u de naam typedefedvervangen door de hierboven gegeven definitie.

De moeilijkheid ligt in de verwijzing naar de syntaxis en leesbaarheid van functies in C en C++, en de typedefkan de leesbaarheid van dergelijke verklaringen verbeteren. De syntaxis is echter geschikt, omdat functies – in tegenstelling tot andere eenvoudigere typen – een retourwaarde en parameters kunnen hebben, dus de soms lange en complexe verklaring van een aanwijzer naar functie.

De leesbaarheid kan erg lastig worden met verwijzingen naar functiearrays en enkele andere, nog meer indirecte smaken.

Om uw drie vragen te beantwoorden

  • Waarom wordt typedef gebruikt?
    Om het lezen van de code te vergemakkelijken – vooral voor verwijzingen naar functies of structuurnamen.

  • De syntaxis ziet er vreemd uit (in de declaratie van de aanwijzer naar functie)
    Die syntaxis is niet voor de hand liggend om te lezen, althans niet bij het begin. Het gebruik van een typedef-declaratie vereenvoudigt het lezen

  • Is er een functieaanwijzer gemaakt om het geheugenadres van een functie op te slaan?
    Ja, een functieaanwijzer slaat het adres van een functie op. Dit heeft niets te maken met de typedefconstructie die alleen het schrijven/lezen van een programma vergemakkelijkt; de compiler breidt gewoon de typedef-definitie uit voordat de eigenlijke code wordt gecompileerd.

Voorbeeld:

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

Antwoord 2, autoriteit 39%

  1. typedefwordt gebruikt om aliassen te typen; in dit geval alias je FunctionFuncnaar void(*)().

  2. De syntaxis ziet er inderdaad vreemd uit, kijk hier eens naar:

    typedef   void      (*FunctionFunc)  ( );
    //         ^                ^         ^
    //     return type      type name  arguments
    
  3. Nee, dit vertelt de compiler gewoon dat het type FunctionFunceen functieaanwijzer zal zijn, het definieerter niet een, zoals dit:

    FunctionFunc x;
    void doSomething() { printf("Hello there\n"); }
    x = &doSomething;
    x(); //prints "Hello there"
    

Antwoord 3, autoriteit 7%

Zonder het woord typedef, zou de declaratie in C++ een variabele FunctionFuncvan type pointer declareren naar functie zonder argumenten, en voidteruggeven.

Met de typedefdefinieert het in plaats daarvan FunctionFuncals een naam voor dat type.


Antwoord 4, autoriteit 2%

Als je C++11 kunt gebruiken, wil je misschien std::functionen usingtrefwoord gebruiken.

using FunctionFunc = std::function<void(int arg1, std::string arg2)>;

Antwoord 5

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

Antwoord 6

Voor een algemeen geval van syntaxis kun je kijken op bijlage A van de ANSI C-norm.

In het Backus-Naur-formulier kun je zien dat typedefhet type storage-class-specifierheeft.

In het type declaration-specifierskun je zien dat je veel soorten specificeerders kunt mixen, waarvan de volgorde er niet toe doet.

Het is bijvoorbeeld correct om te zeggen:

long typedef long a;

om het type ate definiëren als een alias voor long long. Dus om de typedef voor het uitgebreide gebruik te begrijpen, moet je een backus-naur-formulier raadplegen dat de syntaxis definieert (er zijn veel correcte grammatica’s voor ANSI C, niet alleen die van ISO).

Als u typedef gebruikt om een alias voor een functietype te definiëren, moet u de alias op dezelfde plaats plaatsen waar u de identifier van de functie plaatst. In uw geval definieert u het type FunctionFuncals een alias voor een aanwijzer naar functie waarvan de typecontrole is uitgeschakeld bij aanroep en niets retourneert.

Other episodes