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 in der Lage ist, ihnen zu antworten, wäre ich dankbar.
- Warum wird
typedef
verwendet? - Die Syntax sieht seltsam aus; Nachher
void
sollte es keinen Funktionsnamen oder so geben? Es sieht aus wie eine anonyme Funktion. - Wird ein Funktionszeiger zum Speichern der Speicheradresse einer Funktion erstellt?
Also bin ich im Moment verwirrt; Kannst du die Dinge für mich klären?
using FunctionFunc = void (*)();
stattdessen c ++ 11 verwendet werden kann. Es ist ein bisschen klarer, dass Sie nur einen Namen für einen Typ deklarieren (Zeiger auf Funktion)using FunctionFunc = void(void);
*
etwas expliziter ist.Antworten:
typedef
ist ein Sprachkonstrukt, das einem Typ einen Namen zuordnet.Sie verwenden es beispielsweise genauso wie den Originaltyp
mit ihnen wie
Wie Sie sehen können, können Sie den typisierten Namen einfach durch die oben angegebene Definition ersetzen .
Die Schwierigkeit liegt im Zeiger auf Funktionssyntax und 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, daher die manchmal langwierige und komplexe Deklaration eines Zeigers auf die Funktion.Die Lesbarkeit kann mit Zeigern auf Funktionsarrays und einigen anderen, noch indirekteren Varianten sehr schwierig werden.
Um Ihre drei Fragen zu beantworten
Warum wird typedef verwendet? Erleichtert das Lesen des Codes - insbesondere bei Zeigern auf Funktionen oder Strukturnamen.
Die Syntax sieht seltsam aus (im Zeiger auf die Funktionsdeklaration). Diese Syntax ist zumindest zu Beginn nicht offensichtlich zu lesen. Die Verwendung einer
typedef
Deklaration erleichtert stattdessen das LesenWird ein Funktionszeiger zum Speichern der Speicheradresse einer Funktion erstellt? Ja, ein Funktionszeiger speichert die Adresse einer Funktion. Dies hat nichts mit dem
typedef
Konstrukt zu tun, das nur das Schreiben / Lesen eines Programms erleichtert; Der Compiler erweitert lediglich die typedef-Definition, bevor der eigentliche Code kompiliert wird.Beispiel:
quelle
typedef type alias
aber mit Funktionszeigern scheint es nur 2 Argumente zu gebentypedef type
. Ist der Alias standardmäßig auf den im Typargument angegebenen Namen eingestellt?square
und&square
(und tatsächlich*square
und**square
) beziehen sich alle auf denselben Funktionszeiger.typedef int newname
Sienewname
einen Alias fürint
. Mit machentypedef int (*func)(int)
Siefunc
einen Alias fürint (*)(int)
- einen Zeiger auf die Funktion, die einint
Argument nimmt und einenint
Wert zurückgibt.int (*func)(int)
verstehe ich, dass func ein Alias ist, nur ein wenig verwirrt, weil der Alias mit dem Typ verwickelt ist. Alstypedef int INT
Beispiel wäre es einfacher, wenn der typedef-Funktionszeiger eine Form hättetypedef int(*function)(int) FUNC_1
. Auf diese Weise kann ich den Typ und den Alias in zwei separaten Token sehen, anstatt in einem zu vernetzen.typedef
wird für Alias-Typen verwendet; In diesem Fall ist ein AliasingFunctionFunc
fürvoid(*)()
.In der Tat sieht die Syntax seltsam aus. Schauen Sie sich das an:
Nein, dies sagt dem Compiler einfach, dass der
FunctionFunc
Typ ein Funktionszeiger sein wird, er definiert keinen wie diesen:quelle
typedef
hat nicht einen neuen Typ deklarieren. Sie können vieletypedef
definierte Namen desselben Typs haben, die sich nicht unterscheiden (z. B. Überladung von Funktionen). Unter bestimmten Umständentypedef
entspricht ein definierter Name in Bezug auf die Verwendung des Namens nicht genau dem, als was er definiert ist, sondern mehreretypedef
definierte Namen für denselben Namen.Ohne das
typedef
Wort würde die Deklaration in C ++ eine VariableFunctionFunc
vom Typ Zeiger auf die Funktion ohne Argumente deklarieren und zurückgebenvoid
.Mit dem
typedef
definiert es stattdessenFunctionFunc
als Namen für diesen Typ.quelle
Wenn Sie C ++ 11 verwenden können , die Sie verwenden möchten
std::function
undusing
Schlüsselwort.quelle
using
Schlüsselwort wäre wietypedef std::function<void(int, std::string)> FunctionFunc;
, nur für den Fall, dass jemand einen anderen Wrapper um Funktionen ohne C ++ 11quelle
typedef (*double) p
ist das '&' optional?typedef double* p
, um einen Zeiger auf ein Double zu definieren. Wenn Sie denp
Zeiger aus einer primitiven Variablen füllen möchten , müssen Sie das '&' verwenden. Eine Randnotiz, wir Sie * <Pointername>, um einen Zeiger zu dereferenzieren. Das*
wird im Funktionszeiger verwendet, um den Zeiger (Funktionsname) zu dereferenzieren und zu dem Speicherblock zu wechseln, in dem sich die Funktionsanweisungen befinden.Den allgemeinen Fall der Syntax finden Sie in Anhang A des ANSI C-Standards .
In der Backus-Naur-Form von dort können Sie sehen, dass
typedef
der Typ hatstorage-class-specifier
.Im Typ sehen
declaration-specifiers
Sie, dass Sie viele Spezifizierertypen mischen können, deren Reihenfolge keine Rolle spielt.Zum Beispiel ist es richtig zu sagen:
um den Typ
a
als Alias für zu definierenlong long
. Um das typedef über 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 die Kennung der Funktion platziert haben. 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.quelle